"""
Copyright (c) 2012, 2013 Regents of the University of California
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions 
are met:

 - Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
 - Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the
   distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
"""

from django.template import Context, loader
from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseRedirect, HttpResponseBadRequest, Http404
from django.shortcuts import render_to_response, redirect
from django.contrib.admin import site as adminsite
from models import *
import sys
from django.forms.models import inlineformset_factory, modelformset_factory
from operator import itemgetter, attrgetter
from django.contrib.auth.decorators import login_required
from django.utils import simplejson
from django.db.models import Q
import smap.archiver.client
import time
import scipy.interpolate
import calendar
import logging
from dateutil import tz
import datetime
from calendar import timegm
import csv
from django.core.files import File
from random import choice
from django.utils.functional import curry
from django.contrib.admin import widgets
from forms import *
from django.core import serializers
import numpy as np
from django.utils import timezone
from sets import Set
from pmputils import *
from math import exp, log
import types
from django.utils.html import escape, escapejs
from olwidget.widgets import InfoMap
import re
from xhtml2pdf import pisa
import cStringIO
from django.conf import settings
import os
import zipfile
import subprocess
import random
import urllib
import urllib2

global symbol_choices
symbol_choices = ['circle','triangle','cross','square', 'diamond']
global colormap 
colormap = ["#0000ff","#008000","#ff0000","#00bfbf","#bf00bf","#bfbf00", 'orange', '#6f05c1']

@login_required
def index(request): 
    return redirect('/pmp/home/')

@login_required
def home(request): #Building project page is the index page
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    f = make_project_formd(groupL)
    c = {'user': user,
     'projectF': f,
     }
    return render_to_response('index.html',c)

@login_required
def building(request):
    #add ability to add new projects
    #only show projects that are associated with the correct user 
    user = request.user
    if request.method == 'POST':
        if 'select' in request.POST: #if the user has changed the project select dropdown
            if request.POST['projectId'] != "":
                a = Project.objects.get(pk=request.POST['projectId'])
                f = ProjectFormU(instance=a)
            else: #new project form
                f = ProjectFormU
            return render_to_response('buildingInline.html',{'projectFU':f})
        else: #the user clicked the "save changes" button
            if request.POST['projectId'] != "": #existing project
                a = Project.objects.get(pk=request.POST['projectId'])
                f = ProjectFormU(request.POST, request.FILES, instance=a)
            else: #new project
                f = ProjectFormU(request.POST, request.FILES)
                
            if f.is_valid():
                try:
                    form_content = f.save()
                    saveStatus = "Saved successfully"
                except:
                    return HttpResponse(f)
            else:
                saveStatus = "Check form for errors"
            if request.POST['projectId'] != "":
                return render_to_response('buildingInline.html',{'projectFU':f, 'saveStatus': saveStatus,})
            else:
                if f.is_valid():
                    return render_to_response('buildingInline.html',{'projectFU':f, 'saveStatus': saveStatus, 'newF': form_content.pk})
                else:
                    return render_to_response('buildingInline.html',{'projectFU':f, 'saveStatus': saveStatus})   
    else:
        userI = User.objects.get(username=user)
        groupL = userI.groups.all().values_list('pk', flat=True)
        f = make_project_formd(groupL)
        c = {'user': user,
         'projectF': f,
         }
        return render_to_response('buildingInfo.html',c)

@login_required
def comfort(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)
    if request.method == 'POST':
        if 'projectIdChange' in request.POST:
            configFileF = ConfigFileForm(auto_id='id_form_%s')
            configFileFD = ConfigFileFormDrop(auto_id='id_for_%s')
            configFileFD.fields['name'].queryset = ConfigFile.objects.filter(project=request.POST['projectIdChange'], type='setpoint')
            c = {'configFileF' : configFileF, 'configFileFD' : configFileFD}
            return render_to_response('setpoint_inline.html', c)
        else:
            post_data = simplejson.loads(request.body)
        
        if 'form' in post_data: #handle the loading and saving of setpoint analysis mappings 
            configFileNames = ConfigFile.objects.all().values_list('name', flat=True)
            if post_data['form']['name'] in configFileNames:
                try:
                    a = ConfigFile.objects.get(name=post_data['form']['name'], type='setpoint')
                    configFileF = ConfigFileForm(instance=a, auto_id='id_form_%s')
                except:
                    configFileF = ConfigFileForm(post_data['form'], auto_id='id_form_%s')
                    
            else:
                configFileF = ConfigFileForm(post_data['form'], auto_id='id_form_%s')
            projectI = Project.objects.get(pk=int(post_data['form']['projectId']))
            configForm = configFileF.save(commit=False)
            configForm.project = projectI
            configForm.type = 'setpoint'
            configForm.save()
            configFileFD = ConfigFileFormDrop(auto_id='id_for_%s')
            configFileFD.fields['name'].queryset = ConfigFile.objects.filter(project=int(post_data['form']['projectId']))
            f = open('/opt/bpe_toolkit/staticStore/userData/' + post_data['form']['name'] + '_' + str(configForm.pk) + '.json', 'w')
            #for whatever reason, the get_json function of jstree doesn't get the class attributes of the tree, so add it back to the file here
            f.write(simplejson.dumps(post_data['treeJSON']).replace("\" \"", "\"jstree-drop\"").replace("\"  \"", "\"jstree-drop\""))
            c = {'configFileF' : configFileF, 'configFileFD' : configFileFD}
            return render_to_response('setpoint_inline.html', c)
        else: 
            #do some actual analyses
            #deal with times and timezone
            time_zone = tz.gettz(Project.objects.get(pk=post_data['projectId']).timezone)
            time_zone_utc = tz.gettz('UTC')
            dt_format = '%Y-%m-%d %H:%M'          
            start_date = datetime.datetime.fromtimestamp(post_data['start_time']/1000, time_zone)
            end_date = datetime.datetime.fromtimestamp(post_data['end_time']/1000, time_zone)          
            tz_td = start_date.utcoffset()
            tz_offset = (tz_td.days * 86400 + tz_td.seconds) / 3600
            #first get the needed data streams by filtering the metadata db
            query = userFilters(post_data)
            
            #build a list of zones or orientations for a given set of test objects
            def aggregateBuildL(start_date, end_date): #consider moving this function to pmputils
                if post_data['stratDevice'] == 'Cart' or post_data['stratDevice'] == 'cart_pole':
                    query = ['Zone.objects.filter(project=post_data[\'projectId\'], test__start_time__range=(start_date, end_date), test__device__type=\'Cart\', zone_category__pmp_category__in=[\'Thermal comfort\'])']
                else:
                    query = ['Zone.objects.filter(project=post_data[\'projectId\'], test__start_time__lte=start_date, test__device__type=\'ICM\', zone_category__pmp_category__in=[\'Thermal comfort\'])']
                querynew = query[:]
                #query either zone or orientation
                if post_data['aggregate'] == 'zone':
                    querynew.append('.distinct().values_list(\'name\', flat=True)')        
                else:
                    querynew.append('.distinct().values_list(\'orientation\', flat=True).distinct()')
                z_orList = eval(''.join(querynew))
                return z_orList
            
            #build the first part of the query based on analysis type and stratification device type
            if post_data['analysisType'] == 'ras' or post_data['analysisType'] == 'stratComfort':
                if post_data['stratDevice'] == 'Cart' or post_data['stratDevice'] == 'cart_pole':
                    test_objects = eval('Test.objects.filter(start_time__range=(start_date, end_date),zone__project=post_data[\'projectId\'],device__name=\'Cart\').order_by(\'end_time\')' + query)
                if post_data['stratDevice'] == 'Fixed pole' or post_data['stratDevice'] == 'cart_pole':
                    #find a list of devices that have sensors that are for this project and have device instances that are in the correct location
                    fp_devices = eval('Device.objects.filter(type=\'Fixed pole\', sensor__project__pk=post_data[\'projectId\'])' + query.replace('zone','test__zone').replace('test__zone__test__zone_type', 'test__zone__zone_type'))

                #get the correct sensors to pass to smap and their heights in order to graph
                deviceUuids = {}
                sensorHeights = {}
                #get cart stuff first
                if post_data['stratDevice'] == 'Cart' or post_data['stratDevice'] == 'cart_pole':
                    deviceUuids['Cart'] = []
                    sensors = Sensor.objects.filter(device__name='Cart').filter(sensor_type='Thermistor').filter(project=post_data['projectId'])
                    for sensor in sensors:
                        if sensor.sensor_height:
                            deviceUuids['Cart'].append(sensor.uuid)
                            sensorHeights[sensor.uuid] = int(sensor.sensor_height)
                #get pole devices
                if post_data['stratDevice'] == 'Fixed pole' or post_data['stratDevice'] == 'cart_pole':
                    sensors = deviceSensors(fp_devices, post_data['projectId'])
                    for device in fp_devices:
                        deviceUuids[str(device.name)]=[]
                    for sensor in sensors:
                        if sensor.sensor_height:
                            deviceUuids[str(sensor.device)].append(sensor.uuid)
                            sensorHeights[sensor.uuid] = int(sensor.sensor_height)
    
                if post_data['stratDevice'] != 'Fixed pole':
                    #deal with aggregation -- only cart data and cart_pole for now
                    if 'aggregate' in post_data:
                        labels_n = []
                        chart_data_n = []
                        test_objects_s = test_objects #keep static copy of test_objects
                        z_orList = aggregateBuildL(start_date, end_date)
                        #loop over all zones or orientations, filter for matching test_objects, build averaged strats
                        for z_or in z_orList:
                            if post_data['aggregate'] == 'zone':
                                test_objects = test_objects_s.filter(zone__name=z_or)
                            else:
                                test_objects = test_objects_s.filter(zone__orientation=z_or)
                            if len(test_objects) > 0:       
                                chartData = buildRasCharts(test_objects, post_data, time_zone, deviceUuids, sensorHeights)
                                labels_n.append(z_or + ' (' + str(len(test_objects) + chartData[2]) + ')')
                                chart_data_n.append(chartData[0])
                        chart_data = chart_data_n
                        symbols = []
                        labels = labels_n
                        series_colors = chartData[1]
                        alert = False
                    else:
                        chartData = buildRasCharts(test_objects, post_data, time_zone, deviceUuids, sensorHeights)
                        chart_data = chartData[0]
                        symbols = chartData[1]
                        labels = chartData[2]
                        series_colors = chartData[3]
                        alert = chartData[4]
                        
                
                #no aggregation for fixed poles yet--but aggregation should look like that for the comfort chart     
                #fixed poles currently take a 2 minute average of data before the time of interest (should this really be the average of the resampled time?
                else: #fixed poles
                    fp_times = []
                    chart_data = []
                    labels = []
                    symbols = []
                    series_colors = []
                    alert = False
                    #a test is labeled by its end time--so the first test's end time should be after the start date
                    #build a set of times to send to buildStrat based on resample interval given in ui
                    #this whole section of code should be removed once operational hours is capable in smap operators, at which point we should be taking the mean over the resampling period, not just 2 minutes
                    #smapTime_end = int(calendar.timegm(start_date.utctimetuple()))
                    #smapTime_final = int(calendar.timegm(end_date.utctimetuple()))
                    pyDate = start_date
                    increment = int(post_data['resample_s']) * 1000
                    smapTime_start = int(post_data['start_time'])
                    smapTime_final = int(post_data['end_time'])
                    while smapTime_start <= smapTime_final and len(fp_times) <= 15:
                        smapTime_end = smapTime_start + increment
                        if not post_data['ad']:
                            dy = pyDate.weekday()
                            hr = pyDate.hour
                            if post_data['wkd']:
                                if hr >= post_data['sh'] and hr <= post_data['eh'] and dy != 5 and dy != 6:
                                    fp_times.append([smapTime_start, smapTime_end])
                            else:
                                if hr >= post_data['sh'] and hr <= post_data['eh']:
                                    fp_times.append([smapTime_start, smapTime_end])
                        else:
                            fp_times.append([smapTime_start, smapTime_end])
                        pyDate = pyDate + datetime.timedelta(seconds=int(post_data['resample_s']))
                        smapTime_start = int(calendar.timegm(pyDate.utctimetuple())) * 1000
                    
                    s = 0
                    for i in xrange(len(fp_devices)):
                        symbol_s = symbol_choices[s]
                        if len(chart_data) > 15:
                            alert = True
                            break
                        smap_uuids = deviceUuids[str(fp_devices[i].name)]
                        if post_data['analysisType'] == 'stratComfort':
                               smap_comfort_uuids = []
                               for uuid in smap_uuids:
                                   if 3 < sensorHeights[uuid] < 70:
                                       smap_comfort_uuids.append(uuid)
                        #here is where you would add aggregation functionality for fixed poles (build groups of devices that meet criteria and average the buildstrat results)
                        for fptime in fp_times:
                            if post_data['analysisType'] == 'ras':
                                cd = buildStrat(smap_uuids, fptime[0], fptime[1], sensorHeights, False)
                                if len(cd) > 0:
                                    chart_data.append(cd)
                            else: #strat_comfort
                                cd = buildStrat(smap_comfort_uuids, fptime[0], fptime[1], sensorHeights, True)
                                if len(cd) > 0:
                                    chart_data.append(cd)
                            if len(cd) > 0:
                                labels.append(datetime.datetime.utcfromtimestamp(fptime[1]/1000).replace(tzinfo=time_zone_utc).astimezone(time_zone).strftime(dt_format) + ' ' + str(fp_devices[i].name))
                                symbols.append(symbol_s)
                        if s < len(symbol_choices) - 1:
                            s += 1
                        else:
                            s = 0
                
                #if post_data['analysisType'] == 'ras': #not for strat_comfort type
                    #go ahead and make a csv file even if they don't ask for it
                #    f = open('/opt/bpe_toolkit/staticStore/userData/sMAPexport.csv', 'w')
                #    unique_heights = sorted(list(set(sensorHeights.values())))
                #    writer = csv.writer(f)
                #    row = ['']
                #    row.extend(unique_heights)
                ###    writer.writerow(row)
                #    for i in xrange(len(chart_data)):
                #        row = [labels[i]]
                #        for height in unique_heights:
                #            found = False
                #            for point in chart_data[i]:
                ##                if point[1] == height:
                 #                   found = True
                 #                   row.append(point[0])
                 #                   break
                 #           if not found:
                 #               row.append('#N/A')
                 #       writer.writerow(row)
               
                
                if len(chart_data) > 0 and alert == False:
                    success = True
                else:
                    success = False            
                d = simplejson.dumps({"data":chart_data, "labels": labels, "series_colors": series_colors, "symbols": symbols, "alert": alert, "success":success})
                return HttpResponse(d, mimetype="application/json")
            #end of RAS and strat_comfort    
            
            elif post_data['analysisType'] == 'plenum': #plenum analysis
                devicequeries = deviceQuery(post_data)
                test_objects = eval('Test.objects.filter(start_time__lte=start_date,zone__project=post_data[\'projectId\'],device__type=\'Plenum mote\')' + devicequeries[1] + query)
                if 'floor' in post_data:
                    test_objects = test_objects.filter(zone__floor = post_data['floor'])
                if len(test_objects) > 0:
                    #could also just loop through the test objects and build a list of the device names--though would have to strip repeat devices
                    plenum_devices = eval('Device.objects.filter(type=\'Plenum mote\',sensor__project=post_data[\'projectId\'])' + devicequeries[0] + query.replace('zone','test__zone').replace('test__zone__test__zone_type', 'test__zone__zone_type'))
                    sensors = deviceSensors(plenum_devices, post_data['projectId'])
                    project_obj = Project.objects.get(pk=post_data['projectId'])
                    if sensors:
                    #create a dictionary object of device uuids for any icm that is used during this time period
                        deviceUuids = {}
                        for device in plenum_devices:
                            deviceUuids[str(device.name)]={}
                        for sensor in sensors:
                            if sensor.sensor_type == 'Thermistor' or sensor.sensor_type == 'Mote thermistor': #assumes one temperature measurement for the plenum mote
                                deviceUuids[str(sensor.device)] = sensor.uuid
                    if post_data['chart_type'] == 'plenum_map':
                        map = mapChart(test_objects, post_data, time_zone, deviceUuids)
                        return render_to_response("map_inline.html", {
                            "map": map, "type":post_data['chart_type']
                        })
                    else:
                        d = lightingIaqAcousticsCharts(test_objects, post_data, time_zone, deviceUuids, 'Thermal comfort')
                        return HttpResponse(d, mimetype="application/json")
                        
                else:
                    return HttpResponse(simplejson.dumps({'success':False}),mimetype="application/json")
                
            else: #comfort, ieq_model, or ieq_map
                #get the devices instances for the icms for this project and time range
                #test objects are filtered by time, in that the entire user-requested time range must be within the test object time period
                #this time filtering prevents looking at icms instances that don't overlap in time.
                devicequeries = deviceQuery(post_data)
                test_objects = eval('Test.objects.filter(start_time__lte=start_date,zone__project=post_data[\'projectId\'],device__type=\'ICM\')' + devicequeries[1] + query)
                if 'floor' in post_data:
                    test_objects = test_objects.filter(zone__floor = post_data['floor'])
                if len(test_objects) > 0:
                    icm_devices = eval('Device.objects.filter(type=\'ICM\',sensor__project=post_data[\'projectId\'])' + devicequeries[0] + query.replace('zone','test__zone').replace('test__zone__test__zone_type', 'test__zone__zone_type'))
                    sensors = deviceSensors(icm_devices, post_data['projectId'])
                    project_obj = Project.objects.get(pk=post_data['projectId'])
                    
                    #make sure there is some data
                    if sensors:
                    #create a dictionary object of device uuids for any icm that is used during this time period
                        deviceUuids = {}
                        for device in icm_devices:
                            deviceUuids[str(device.name)]={}
                        for sensor in sensors:
                            if sensor.sensor_type == 'Relative humidity':
                                deviceUuids[str(sensor.device)]['rh'] = sensor.uuid
                            elif sensor.sensor_type == 'Globe temperature (pp-ball)':
                                deviceUuids[str(sensor.device)]['glb'] = sensor.uuid
                            elif sensor.sensor_type == 'Thermistor':
                                deviceUuids[str(sensor.device)]['dbt'] = sensor.uuid
                            elif sensor.sensor_type == 'Anemometer':
                                deviceUuids[str(sensor.device)]['anem'] = sensor.uuid
                        
                        if post_data['analysisType'] == 'comfort':
                            if post_data['chart_type'] == 'map_top':
                                map = mapChart(test_objects, post_data, time_zone, deviceUuids)
                                try:
                                    return render_to_response("map_inline.html", {
                                        "map": map, "heating_sp": round(project_obj.occupied_heating_sp,1), "cooling_sp": round(project_obj.occupied_cooling_sp,1),"type":post_data['chart_type']
                                    })
                                except:
                                     return HttpResponse(simplejson.dumps({'success':False}),mimetype="application/json")
                            
                            elif post_data['chart_type'] == 'comfort_tool': #rh vs top chart
                                if 'aggregate' in post_data:
                                    icmData_n = []
                                    test_objects_s = test_objects #keep static copy of test_objects
                                    z_orList = aggregateBuildL(start_date, end_date)
                                    for z_or in z_orList:
                                        if post_data['aggregate'] == 'zone':
                                            test_objects = test_objects_s.filter(zone__name=z_or)
                                            
                                        else:
                                            test_objects = test_objects_s.filter(zone__orientation=z_or)
                                        if len(test_objects) > 0:
                                            icmObj = buildComfortChart(test_objects, post_data, time_zone, deviceUuids)
                                            #apply label to icmObj
                                            if icmObj:
                                                icmObj['label'] = z_or + ' (' + str(len(test_objects)) + ')'
                                                icmData_n.append(icmObj)
                                    icmData = icmData_n
                                else:
                                    icmData = buildComfortChart(test_objects, post_data, time_zone, deviceUuids)
                                icmData = sorted(icmData, key=itemgetter('label'))
    
                                ct_json = []
                                labels = {}
                                counter = 0
                                for icm in icmData:
                                    group = counter
                                    labels[str(group)] = icm['label']
                                    for i in xrange(len(icm['rh'])):
                                        json_point = {}
                                        try:
                                            json_point['group'] = group
                                            json_point['ta'] = round(FtoC(icm['dbt'][i]),1)
                                            json_point['rh'] = round(icm['rh'][i],0)
                                            if 'anem' in icm:
                                                json_point['vel'] = round(icm['anem'][i] / 196.85,2) #convert from fpm to m/s
                                            else:
                                                json_point['vel'] = 0.15
                                            json_point['tr'] = round(globetemp(FtoC(icm['dbt'][i]), json_point['vel'], FtoC(icm['glb'][i]), 0.038, 0.95),1)
                                            json_point['met'] = round(float(icm['met']),2)
                                            json_point['clo'] = round(float(icm['clo']),2)
                                            json_point['datetime'] = icm['datetime'][i]
                                            ct_json.append(json_point)
                                        except:
                                            continue
                                    counter += 1
                                
                                if len(icmData) > 0:
                                    return render_to_response('comfort_tool.html', {'data': simplejson.dumps(ct_json), 'tz': tz_offset, 'labels':simplejson.dumps([labels])})
                                else:
                                    return HttpResponse(simplejson.dumps({'success':False}),mimetype="application/json")
                                
                            
                                #temporary code to give boxplot of avg days
                                #if post_data['avg_day']:
                                #    categories = [i for i in range(24)]
                                #    outliers = []
                                #    day_data = [[] for i in range(24)]
                                #    bp_data = [[] for i in range(24)]
                                #    for icm in icmData:
                                #        for i in xrange(len(icm['datetime'])):
                                #            indexH = datetime.fromtimestamp(icm['datetime'][i]/1000, time_zone).hour 
                                #            if icm['to'][i] > 0:
                                #                day_data[indexH].append(icm['to'][i])
                                    #return HttpResponse(simplejson.dumps({'data':icmData}),mimetype="application/json")
                                #    for i in xrange(len(day_data)):
                                #        hourBP = fivenum(day_data[i])
                                #        bp_data[i] = hourBP[0:5]
                                #        if len(hourBP[5]) > 0:
                                #            for elem in hourBP[5]:
                                #                outliers.append([i,elem]) 
                                #    return HttpResponse(simplejson.dumps({'data':bp_data, 'categories':categories, 'outliers':outliers}),mimetype="application/json")
                            
                            else: #spline_top
                                chartData = buildComfortChart(test_objects, post_data, time_zone, deviceUuids)
                                d = simplejson.dumps({'data':chartData})
                                return HttpResponse(d, mimetype="application/json")                                    
                                
                        
                        elif post_data['analysisType'] == 'ieq_model':
                            if post_data['chart_type'] == 'ieq_map':
                                map = ieqMapChart(test_objects, post_data, time_zone, deviceUuids, 'tc')
                                ieq_model = int(post_data['ieq_model']['name'])
                                if ieq_model == 4:
                                    pmp = True
                                else:
                                    pmp = False
                                return render_to_response("map_inline.html", {
                                    "map": map, "type":'ieq_map', "pmp":pmp,
                                })
                            else: #run the ieq model
                                model_data = ieqModel(test_objects, post_data, start_date, end_date, 'tc', deviceUuids, time_zone)
                                return HttpResponse(simplejson.dumps(model_data),mimetype="application/json")
                else: #if no test objects, return success false
                    return HttpResponse(simplejson.dumps({'success':False}),mimetype="application/json")
                        
                     
    else:
        c = {'user': user, 'projectF' : projectF}
        return render_to_response('tcAnalysis.html', c)

@login_required
def setpoint(request):
    post_data = simplejson.loads(request.body)
    time_zone = tz.gettz(Project.objects.get(pk=post_data['projectId']).timezone)
    paths_dict = post_data['paths_dict']
    start = post_data['start']
    end = post_data['end']
    resample_s = post_data['resample_s']
    hist_data = []
    diffData = {}
    queries = []
    success = False
    
    c = smap.archiver.client.SmapClient(base='http://new.openbms.org/backend', key=['WE4iJWG7k575AluJ9RJyAZs25UO72Xu0b4RA','SA2nYWuHrJxmPNK96pdLKhnSSYQSPdALkvnA'])
    if 'fixed' in paths_dict:
        paths_dl = paths_dict['points']
        projectObj = Project.objects.get(pk=post_data['projectId'])
        f_setpoint_low = str(int(projectObj.occupied_heating_sp))
        f_setpoint_high = int(projectObj.occupied_cooling_sp)
    elif 'custom_fixed_low' in paths_dict:
        paths_dl = paths_dict['points']
        f_setpoint_low = paths_dict['custom_fixed_low']
        if paths_dict['custom_fixed_high'] != '':
            f_setpoint_high = int(paths_dict['custom_fixed_high'])
        else:
            f_setpoint_high = False
    else:
        paths_dl = paths_dict
        f_setpoint_low = False
        f_setpoint_high = False
    for i in paths_dl:
        if f_setpoint_low:
            queryS = 'apply add(-' + f_setpoint_low + ') < window(first, field=\'second\', width=' + str(resample_s) + ') to data in (' + str(start) + ',' + str(end) + ') limit 10000000 where Path = \"' + i + '\"'
        else:
            queryS = 'apply diff(axis=1) < paste(sort=\'Metadata/Extra/Type\') < window(first, field=\'second\', width=' + str(resample_s) + ') to data in (' + str(start) + ',' + str(end) + ') limit 10000000 where Path = \"' + paths_dl[i] + '\" or Path = \"' + i + '\"'
        queries.append(queryS)
        #return HttpResponse(queryS)
        try:
            data = c.query(queryS)
        except:
            return HttpResponse(queryS)
        #return HttpResponse(data[0]['Readings'])
        try:
            data = np.array(data[0]['Readings'])
            #filter data
            if not post_data['ad']:
                wkd = post_data['wkd']
                sh = post_data['sh']
                eh = post_data['eh']
                data = filterData(data, time_zone, wkd, sh, eh)
            if f_setpoint_low and f_setpoint_high:
                path_hist_data = []
                deadband = f_setpoint_high - int(f_setpoint_low)
                for diff in list(data[:,1]):
                    if diff <= 0:
                        path_hist_data.append(diff)
                    elif diff >= deadband:
                        path_hist_data.append(diff - deadband)
                    else:
                        path_hist_data.append(0)
                hist_data.extend(path_hist_data)
                diffData[i] = path_hist_data
            else:
                hist_data.extend(list(data[:,1]))
                diffData[i] = list(data[:,1])
            success = True
        except:
            success = False
    hist_mean = np.mean(hist_data)
    hist_std = np.std(hist_data)
    d = simplejson.dumps({'hist_data':hist_data, 'diffData':diffData, 'success': success, 'queries': queries, 'mean':hist_mean,'std':hist_std })
    return HttpResponse(d, mimetype="application/json")

@login_required
def trending(request, tree=0):
    user = request.user 
    if request.method == 'POST':
        post_data = simplejson.loads(request.body)
        #make a list of test start and stop times
        start_times = []
        end_times = []
        path = post_data['path']
        if path[1] == 'Devices' or path[1] == 'Sensor Type':
            path_stop = 3
        else:
            path_stop = 5
        if len(path) > path_stop: #if the user has selected an individual sensor or sensors
            if path[1] == 'Devices' or path[1] == 'Orientation':
                uuids = Sensor.objects.filter(device__name=path[path_stop-1]).filter(name=path[path_stop]).filter(project=post_data['projectId'])
                test_obj = Test.objects.filter(device__name=path[path_stop]).filter(device__sensor__project=post_data['projectId']).distinct()
                for obj in test_obj:
                    try:
                        end_times.append(timegm(obj.end_time.timetuple()) * 1000)
                        start_times.append(timegm(obj.start_time.timetuple()) * 1000)
                    except:
                        pass
            else:
                uuids = Sensor.objects.filter(name=path[path_stop]).filter(project=post_data['projectId'])
        else: #if the user has selected the level above sensor
            if path[1] == 'Devices' or path[1] == 'Orientation':
                uuids = Sensor.objects.filter(device__name=path[path_stop-1]).filter(project=post_data['projectId'])
                test_obj = Test.objects.filter(device__name=path[path_stop-1]).filter(device__sensor__project=post_data['projectId']).distinct()
                for obj in test_obj:
                    try:
                        end_times.append(timegm(obj.end_time.timetuple()) * 1000)
                        start_times.append(timegm(obj.start_time.timetuple()) * 1000)
                    except:
                        pass
            else: #sensor type
                uuids = Sensor.objects.filter(sensor_type=path[path_stop-1]).filter(project=post_data['projectId'])
            
        
        metadata = serializers.serialize('json', uuids, fields=('uuid','path','name','pmp_category','sensor_height','sensor_type'))
        #also send the start/end times for each test associated with these devices in order to draw the rectangles on the chart
        return HttpResponse(simplejson.dumps({'metadata': metadata, 'start_times': start_times, 'end_times': end_times}),mimetype="application/json")
    else:
        userI = User.objects.get(username=user)
        groupL = userI.groups.all().values_list('pk', flat=True)
        projectF = make_project_form(groupL)       
        c = Context({
                'projectF': projectF,
                'user' : user,
                'default_tree_id' : str(tree),
                })
    
        t = loader.get_template('trending.html')
    return HttpResponse(t.render(c))

@login_required
def lighting(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)
    
    if request.method == 'POST':
        post_data = simplejson.loads(request.body)
        #deal with times and timezone
        time_zone = tz.gettz(Project.objects.get(pk=post_data['projectId']).timezone)
        time_zone_utc = tz.gettz('UTC')
        dt_format = '%Y-%m-%d %H:%M'
        start_date = datetime.datetime.fromtimestamp(post_data['start_time']/1000, time_zone)
        end_date = datetime.datetime.fromtimestamp(post_data['end_time']/1000, time_zone)          
        tz_td = start_date.utcoffset()
        tz_offset = (tz_td.days * 86400 + tz_td.seconds) / 3600
        dt_format = '%Y-%m-%d %H:%M:%S'
        analysisType = post_data['analysisType']
        query = userFilters(post_data)
        #add devices as a query option
        devicequeries = deviceQuery(post_data)
        
        #check for model short term or long term type and apply the appropriate test filter
        model_st = False
        if 'time_length' in post_data:
            if post_data['time_length'] == 'st':
                model_st = True
            else:
                model_st = False
        #find lighting test objects
        if analysisType == 'lightingST' or model_st:
            test_objects = eval('Test.objects.filter(start_time__range=(start_date, end_date),device__sensor__pmp_category=\'Lighting\',zone__project=post_data[\'projectId\'])' + devicequeries[1] + query + '.order_by(\'start_time\')')
        else:
            #if doing long term analysis, then the user chosen time period must fall entirely within the available data of the test object
            test_objects = eval('Test.objects.filter(start_time__lte=start_date,device__sensor__pmp_category=\'Lighting\',zone__project=post_data[\'projectId\'])' + query + devicequeries[1])
            if 'floor' in post_data:
                test_objects = test_objects.filter(zone__floor = post_data['floor'])
        lighting_devices = eval('Device.objects.filter(sensor__pmp_category=\'Lighting\',sensor__project__pk=post_data[\'projectId\'])' +  query.replace('zone','test__zone').replace('test__zone__test__zone_type', 'test__zone__zone_type') + devicequeries[0])
        sensors = deviceSensors(lighting_devices, post_data['projectId'])
        #make sure there is some data
        if sensors:
        #create a dictionary object of device uuids for any iaq sensor that is used during this time period
            deviceUuids = {}
            for sensor in sensors:
                if sensor.pmp_category == 'Lighting': #don't include the non-lighting sensors
                    deviceUuids[str(sensor.device)] = sensor.uuid
            
            if analysisType == 'lightingST' or analysisType == 'lightingLT':
                if post_data['chart_type'] == 'map_lighting':
                    map = mapChart(test_objects, post_data, time_zone, deviceUuids)
                    return render_to_response("map_inline.html", {
                        "map": map,"conditionG": float(post_data['conditions']), "conditionY": float(post_data['conditions'])-0.1*float(post_data['conditions']),"type":post_data['chart_type']
                    })
                else:
                    d = lightingIaqAcousticsCharts(test_objects, post_data, time_zone, deviceUuids, 'Lighting')
            
            else: #run the ieq model
                if post_data['chart_type'] == 'ieq_map':
                    map = ieqMapChart(test_objects, post_data, time_zone, deviceUuids, 'lighting')
                    ieq_model = int(post_data['ieq_model']['name'])
                    if ieq_model == 4:
                        pmp = True
                    else:
                        pmp = False
                    return render_to_response("map_inline.html", {
                        "map": map, "type":'ieq_map', "pmp":pmp,
                    })
                else:
                    model_data = ieqModel(test_objects, post_data, start_date, end_date, 'lighting', deviceUuids, time_zone)
                    d = simplejson.dumps(model_data)                        
                
            return HttpResponse(d, mimetype="application/json")
        else:
            return HttpResponse('alert')
                        
    else:
        c = {'user': user, 'projectF' : projectF}
        return render_to_response('lightingAnalysis.html', c)

@login_required
def iaq(request):
    user = request.user
    type = 'iaq'  
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)
    
    if request.method == 'POST':
        post_data = simplejson.loads(request.body)
        #deal with times and timezone
        time_zone = tz.gettz(Project.objects.get(pk=post_data['projectId']).timezone)
        time_zone_utc = tz.gettz('UTC')
        dt_format = '%Y-%m-%d %H:%M'
        start_date = datetime.datetime.fromtimestamp(post_data['start_time']/1000, time_zone)
        end_date = datetime.datetime.fromtimestamp(post_data['end_time']/1000, time_zone)          
        tz_td = start_date.utcoffset()
        tz_offset = (tz_td.days * 86400 + tz_td.seconds) / 3600
   
        #get user selected filters
        query = userFilters(post_data)
        #add devices as a query option if its in the post data (this could likely be integrated into userFilters)
        devicequeries = deviceQuery(post_data)
        
        #check for model short term or long term type and apply the appropriate test filter
        model_st = False
        if 'time_length' in post_data:
            if post_data['time_length'] == 'st':
                model_st = True
            else:
                model_st = False
        #find iaq test objects
        if post_data['analysisType'] == 'iaqST' or model_st:
            test_objects = eval('Test.objects.filter(start_time__range=(start_date, end_date),device__sensor__pmp_category=\'IAQ\',zone__project=post_data[\'projectId\'])' + query + '.order_by(\'start_time\')' + devicequeries[1])
        else:
            #if doing long term analysis, then the user chosen time period must fall entirely within the available data of the test object
            test_objects = eval('Test.objects.filter(start_time__lte=start_date, device__sensor__pmp_category=\'IAQ\',zone__project=post_data[\'projectId\'])' + query + devicequeries[1])
            if 'floor' in post_data:
                test_objects = test_objects.filter(zone__floor = post_data['floor'])
        iaq_devices = eval('Device.objects.filter(sensor__pmp_category=\'IAQ\', sensor__project__pk=post_data[\'projectId\'])' +  query.replace('zone','test__zone').replace('test__zone__test__zone_type', 'test__zone__zone_type') + devicequeries[0])
        sensors = deviceSensors(iaq_devices, post_data['projectId'])
        #make sure there is some data
        if sensors:
        #create a dictionary object of device uuids for any iaq sensor that is used during this time period
            deviceUuids = {}
            for sensor in sensors:
                if sensor.pmp_category == 'IAQ': #don't include the non-iaq sensors
                    deviceUuids[str(sensor.device)] = sensor.uuid
    
            if post_data['analysisType'] == 'iaqST' or post_data['analysisType'] == 'iaqLT':
                if post_data['chart_type'] == 'map_iaq':
                    map = mapChart(test_objects, post_data, time_zone, deviceUuids)
                    return render_to_response("map_inline.html", {
                        "map": map,"conditionG": float(post_data['conditions']), "conditionY": float(post_data['conditions'])-200, "type":post_data['chart_type']
                    })
                else:
                    d = lightingIaqAcousticsCharts(test_objects, post_data, time_zone, deviceUuids, 'IAQ')
            
            else: #run the ieq model
                if post_data['chart_type'] == 'ieq_map':
                    map = ieqMapChart(test_objects, post_data, time_zone, deviceUuids, 'iaq')
                    ieq_model = int(post_data['ieq_model']['name'])
                    if ieq_model == 4:
                        pmp = True
                    else:
                        pmp = False
                    return render_to_response("map_inline.html", {
                        "map": map, "type":'ieq_map', "pmp":pmp,
                    })
                else:
                    model_data = ieqModel(test_objects, post_data, start_date, end_date, type, deviceUuids, time_zone)                        
                    d = simplejson.dumps(model_data)                        
                    
            return HttpResponse(d, mimetype="application/json")
        else:
            return HttpResponse('alert')
                                         
    else:
        c = {'user': user, 'projectF' : projectF}
        return render_to_response('iaqAnalysis.html', c)

@login_required
def acoustics(request):
    user = request.user
    type = 'acc'  
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)
    
    if request.method == 'POST':
        post_data = simplejson.loads(request.body)
        #deal with times and timezone
        time_zone = tz.gettz(Project.objects.get(pk=post_data['projectId']).timezone)
        time_zone_utc = tz.gettz('UTC')
        dt_format = '%Y-%m-%d %H:%M'
        start_date = datetime.datetime.fromtimestamp(post_data['start_time']/1000, time_zone)
        end_date = datetime.datetime.fromtimestamp(post_data['end_time']/1000, time_zone)          
        tz_td = start_date.utcoffset()
        tz_offset = (tz_td.days * 86400 + tz_td.seconds) / 3600
   
        #get user selected filters
        query = userFilters(post_data)
        
        #check for model short term or long term type and apply the appropriate test filter
        model_st = False
        if 'time_length' in post_data:
            if post_data['time_length'] == 'st':
                model_st = True
            else:
                model_st = False
        #find acoustics test objects
        if post_data['analysisType'] == 'acousticsST' or model_st:
            test_objects = eval('Test.objects.filter(start_time__range=(start_date, end_date),device__sensor__pmp_category=\'Acoustics\',zone__project=post_data[\'projectId\'])' + query + '.order_by(\'start_time\')')
            if 'floor' in post_data:
                test_objects = test_objects.filter(zone__floor = post_data['floor'])
        else:
            #if doing long term analysis, then the user chosen time period must fall entirely within the available data of the test object
            test_objects = eval('Test.objects.filter(start_time__lte=start_date, device__sensor__pmp_category=\'Acoustics\', zone__project=post_data[\'projectId\'])' + query + '.order_by(\'start_time\')')
        acoustics_devices = eval('Device.objects.filter(sensor__pmp_category=\'Acoustics\', sensor__project__pk=post_data[\'projectId\'])' +  query.replace('zone','test__zone').replace('test__zone__test__zone_type', 'test__zone__zone_type'))
        sensors = deviceSensors(acoustics_devices, post_data['projectId'])
        #make sure there is some data
        
        if sensors:
        #create a dictionary object of device uuids for any acoustics sensor that is used during this time period
            deviceUuids = {}
            for sensor in sensors:
                if sensor.pmp_category == 'Acoustics': #don't include the non-acoustics sensors
                    deviceUuids[str(sensor.device)] = sensor.uuid
    
            if post_data['analysisType'] == 'acousticsST' or post_data['analysisType'] == 'acousticsLT':
                if post_data['chart_type'] == 'map_acoustics':
                    map = mapChart(test_objects, post_data, time_zone, deviceUuids)
                    return render_to_response("map_inline.html", {
                        "map": map,"conditionG": float(post_data['conditions'][0]), "conditionY": float(post_data['conditions'][1]),"type":post_data['chart_type']
                    })
                else:
                    d = lightingIaqAcousticsCharts(test_objects, post_data, time_zone, deviceUuids, 'Acoustics')
            
            else: #run the ieq model
                if post_data['chart_type'] == 'ieq_map':
                    map = ieqMapChart(test_objects, post_data, time_zone, deviceUuids, type)
                    ieq_model = int(post_data['ieq_model']['name'])
                    if ieq_model == 4:
                        pmp = True
                    else:
                        pmp = False
                    return render_to_response("map_inline.html", {
                        "map": map, "type":'ieq_map', "pmp":pmp,
                    })
                else:
                    model_data = ieqModel(test_objects, post_data, start_date, end_date, type, deviceUuids, time_zone)                        
                    d = simplejson.dumps(model_data)                            
            
            return HttpResponse(d, mimetype="application/json")
        else:
            return HttpResponse('alert')
                                         
    else:
        c = {'user': user, 'projectF' : projectF}
        return render_to_response('acousticsAnalysis.html', c)


@login_required
def tree(request):
    
    #note on time filtering. if the device instance is short term (lighting, acoustics, cart), then the device instance start time must be
    #less than the user chosen time range. otherwise if the device instance is long term (icm, fixed pole)--then the opposite is true--the entire user chosen
    #time period must fall within the device instance time period
    analysisType = request.GET['analysisType']
    stratDevice = str(request.GET['stratDevice'])
    projectId = int(request.GET['projectId'])
    if request.GET['analysisType'] != "trending":
        time_zone = tz.gettz(Project.objects.get(pk=projectId).timezone)
        start_date = datetime.datetime.fromtimestamp(int(request.GET['start_time'])/1000, time_zone)
        end_date = datetime.datetime.fromtimestamp(int(request.GET['end_time'])/1000, time_zone)
    jdata = []
    
    #start building the query based on the device type and project
    if analysisType == 'trending' or analysisType == 'setpoint':
        #if analysisType == 'trending': #add a few more organizational styles for the trending page
            #orientation organization
        orientationL = Zone.objects.filter(project=projectId).distinct().values_list('orientation', flat=True).distinct()
        oChildren = []
        for o in orientationL:
            zChildren = []
            ztL = Zone.objects.filter(project=projectId, orientation=o).distinct().values_list('zone_type', flat=True).distinct()
            for zt in ztL:
                dChildren = []
                deviceL = Test.objects.filter(zone__project=projectId, zone__zone_type=zt, zone__orientation=o).values_list('device', flat=True).distinct()
                for d in deviceL:
                    deviceQ = Device.objects.get(pk=d)
                    sChildren = []
                    sensorL = Sensor.objects.filter(device=deviceQ).filter(project=projectId).distinct().values_list('name', flat=True)
                    for s in sensorL:
                        if analysisType == 'trending':
                            sChildren.append({ "data": {'title': str(s), "icon" : "/static/smap/img/plotable.png"}})
                        else:
                            sChildren.append({ "data": {'title': str(s)}})
                    sChildren.sort()
                    if analysisType == 'trending':
                        dChildren.append({ "data": {'title': str(deviceQ.name), "icon" : "/static/smap/img/plotable.png"}, "children": sChildren, "state": "closed" })
                    else:
                        dChildren.append({ "data": {'title': str(deviceQ.name)}, "children": sChildren, "state": "closed" })
                
                dChildren = sorted(dChildren, key=lambda x: x['data']['title'])
                if len(deviceL) > 0:
                    if analysisType == 'trending':
                        zChildren.append({ "data": {'title': str(zt), "icon" : "/static/smap/img/collection.png"}, "children": dChildren, "state": "closed" })
                    else:
                        zChildren.append({ "data": {'title': str(zt)}, "children": dChildren, "state": "closed" })
            zChildren.sort()
            if len(zChildren) > 0:
                if analysisType == 'trending':
                    oChildren.append({ "data": {'title': str(o), "icon" : "/static/smap/img/collection.png"}, "children": zChildren, "state": "closed" })
                else:
                    oChildren.append({ "data": {'title': str(o)}, "children": zChildren, "state": "closed" })
        oChildren.sort()
        #sensor type organization
        stL = Sensor.objects.filter(project=projectId).values_list('sensor_type', flat=True).distinct()
        stChildren = []
        for st in stL:
            if st != '':
                sChildren = []
                sensorL = Sensor.objects.filter(sensor_type=st, project=projectId).values_list('name', flat=True).distinct()
                for s in sensorL:
                    if analysisType == 'trending':
                        sChildren.append({ "data": {'title': str(s), "icon" : "/static/smap/img/plotable.png"}})
                    else:
                        sChildren.append({ "data": {'title': str(s)}})
                sChildren.sort()
                if analysisType == 'trending':
                    stChildren.append({ "data": {'title': str(st), "icon" : "/static/smap/img/plotable.png"}, "children": sChildren, "state": "closed" })
                else:
                    stChildren.append({ "data": {'title': str(st)}, "children": sChildren, "state": "closed" })
            
        
        deviceQ = Device.objects.filter(sensor__project=projectId).distinct()
        dChildren = []
        for d in deviceQ:
            sChildren = []
            sensorL = Sensor.objects.filter(device=d).filter(project=projectId).distinct().values_list('name', flat=True)
            for s in sensorL:
                if analysisType == 'trending':
                    sChildren.append({ "data": {'title': str(s), "icon" : "/static/smap/img/plotable.png"}})
                else:
                    sChildren.append({ "data": {'title': str(s), }})
            sChildren.sort()
            if analysisType == 'trending':
                dChildren.append({ "data": {'title': str(d.name), "icon" : "/static/smap/img/plotable.png"}, "children": sChildren, "state": "closed" })
            else:
                dChildren.append({ "data": {'title': str(d.name)}, "children": sChildren, "state": "closed" })
        dChildren = sorted(dChildren, key=lambda x: x['data']['title'])
        
        if analysisType == 'trending':
            tChildren = [{ "data": {'title':"Devices", "icon" : "/static/smap/img/collection.png"}, "children": dChildren, "state": "closed" },{ "data": {'title':"Orientation", "icon" : "/static/smap/img/collection.png"}, "children": oChildren, "state": "closed" },{ "data": {'title':"Sensor Type", "icon" : "/static/smap/img/collection.png"}, "children": stChildren, "state": "closed" }]
            jdata.append({ "data": {'title':"CBE Toolkit",  "icon" : "/static/smap/img/collection.png"}, "children": tChildren, "state": "closed" })
        else:
            tChildren = [{ "data": {'title':"Devices"}, "children": dChildren, "state": "closed" },{ "data": {'title':"Orientation"}, "children": oChildren, "state": "closed" },{ "data": {'title':"Sensor Type"}, "children": stChildren, "state": "closed" }]
            jdata.append({ "data": {'title':"CBE Toolkit"}, "children": tChildren, "state": "closed" })
    #end trending and setpoint tree code
    
    elif analysisType == 'ras' or analysisType == 'stratComfort':
        if stratDevice == 'cart_pole':
            query = ['Zone.objects.filter(project=projectId, test__start_time__range=(start_date, end_date), zone_category__pmp_category__in=[\'Thermal comfort\']).filter(Q(test__device__type=\'Cart\') | Q(test__device__type=\'Fixed pole\'))']
        elif stratDevice == 'Cart':
            query = ['Zone.objects.filter(project=projectId, test__start_time__range=(start_date, end_date), zone_category__pmp_category__in=[\'Thermal comfort\']).filter(test__device__type=\'Cart\')']
        else: #fixed poles
            query = ['Zone.objects.filter(project=projectId, test__start_time__lte=start_date, zone_category__pmp_category__in=[\'Thermal comfort\'],test__device__type=\'%s\')' % stratDevice]
    elif analysisType == 'lightingLT':
        query = ['Zone.objects.filter(project=projectId, test__start_time__lte=start_date, test__device__sensor__pmp_category=\'Lighting\', zone_category__pmp_category__in=[\'Lighting\'])']
    elif analysisType == 'lightingST':
        query = ['Zone.objects.filter(project=projectId, test__start_time__range=(start_date, end_date), test__device__sensor__pmp_category=\'Lighting\', zone_category__pmp_category__in=[\'Lighting\'])']
    elif analysisType == 'iaqLT':
        query = ['Zone.objects.filter(project=projectId, test__start_time__lte=start_date, test__device__sensor__pmp_category=\'IAQ\', zone_category__pmp_category__in=[\'IAQ\'])']
    elif analysisType == 'iaqST':
        query = ['Zone.objects.filter(project=projectId, test__start_time__range=(start_date, end_date), test__device__sensor__pmp_category=\'IAQ\', zone_category__pmp_category__in=[\'IAQ\'])']
    elif analysisType == 'acousticsLT':
        query = ['Zone.objects.filter(project=projectId, test__start_time__lte=start_date, test__device__sensor__pmp_category=\'Acoustics\', zone_category__pmp_category__in=[\'Acoustics\'])']
    elif analysisType == 'acousticsST':
        query = ['Zone.objects.filter(project=projectId, test__start_time__range=(start_date, end_date), test__device__sensor__pmp_category=\'Acoustics\', zone_category__pmp_category__in=[\'Acoustics\'])']
    elif analysisType == 'plenum':
        query = ['Zone.objects.filter(project=projectId, test__start_time__lte=start_date, test__device__type=\'Plenum mote\', zone_category__pmp_category__in=[\'Thermal comfort\'])']
    else: #comfort 
        query = ['Zone.objects.filter(project=projectId, test__start_time__lte=start_date, test__device__type=\'ICM\', zone_category__pmp_category__in=[\'Thermal comfort\'])']

    try:
        if request.GET['floor'] != 'none':
            query.append('.filter(floor__floor=\'%s\')' % request.GET['floor'])
    except:
        pass
        
    if analysisType != 'trending' and analysisType != 'setpoint':
        #start with floor list and zones for each floor
        querynew = query[:]
        querynew.append('.distinct().values_list(\'floor\', flat=True)')
        floorList = eval(''.join(querynew))
        floorChildren = []
        for flr in floorList:
            flr = str(flr)
            children = []
            querynew = query[:]
            querynew.append('.filter(floor=str(flr)).distinct().values_list(\'name\', flat=True)')        
            zoneList = eval(''.join(querynew))
            for zone in zoneList:
                children.append(str(zone))
            children.sort()
            floorChildren.append({ "data" : "Floor %s" % str(flr), "children": children, "state" : "open" })
        if len(floorChildren) > 0:
            jdata.append({ "data": "Zone", "children": floorChildren, "state": "closed" })
        
        children = []
        querynew = query[:]
        querynew.append('.distinct().values_list(\'orientation\', flat=True)')
        orientationList = eval(''.join(querynew))
        for o in orientationList:
            children.append(str(o))
        children.sort()
        if len(children) > 0:
            jdata.append({ "data" : "Orientation", "children": children, "state" : "closed" })
        
        children = []
        querynew = query[:] 
        querynew.append('.distinct().values_list(\'zone_type\', flat=True)')
        zoneList = eval(''.join(querynew))
        for s in zoneList:
            children.append(str(s))
        children.sort()
        if len(children) > 0:
            jdata.append({ "data" : "Zone Type", "children": children, "state" : "closed" })
        
        children = []
        querynew = query[:]
        querynew.append('.distinct().values_list(\'space_type\', flat=True)')
        spaceList = eval(''.join(querynew))
        for p in spaceList:
            children.append(str(p))
        children.sort()
        if len(children) > 0:
            jdata.append({ "data" : "Space Type", "children": children, "state" : "closed" })
        
        if analysisType != 'acousticsLT' and analysisType != 'acousticsST' and analysisType != 'ras' and analysisType != 'stratComfort': #give list of ICMs
            if analysisType == 'lightingST':
                deviceList = Device.objects.filter(type='ICM', sensor__project=projectId,sensor__pmp_category = 'Lighting',test__start_time__range=(start_date, end_date)).distinct()
            elif analysisType == 'lightingLT':
                deviceList = Device.objects.filter(type='ICM', sensor__project=projectId,sensor__pmp_category = 'Lighting',test__start_time__lte=start_date).distinct()
            elif analysisType == 'iaqLT':
                deviceList = Device.objects.filter(type='ICM', sensor__project=projectId,sensor__pmp_category = 'IAQ',test__start_time__lte=start_date).distinct()
            elif analysisType == 'iaqST':
                deviceList = Device.objects.filter(type='ICM', sensor__project=projectId,sensor__pmp_category = 'IAQ',test__start_time__range=(start_date, end_date)).distinct()
            else:
                deviceList = Device.objects.filter(type='ICM', sensor__project=projectId,test__start_time__lte=start_date).distinct()
            
            if request.GET['floor'] != 'none': #this needs work
               deviceList.filter(test__zone__floor=request.GET['floor'])
            deviceList = deviceList.values_list('name', flat=True)
            children = []
            for device in deviceList:
                children.append(str(device))
            children.sort()
            if len(children) > 0:
                jdata.append({ "data" : "Devices", "children": children, "state" : "closed" })
    return HttpResponse(simplejson.dumps(jdata),mimetype="application/json")

@login_required
def utils(request):
    if request.method == "GET":
        if request.GET['utilType'] == 'chart_image':
            chart_image_form = ChartImageForm(auto_id="id_image_%s")
            if 'mapSummary' in request.GET:
                mapSummary = True
            else:
                mapSummary = False
            return render_to_response('chartImageInline.html', {'chart_image_form':chart_image_form, 'map':request.GET['map'], 'mapSummary':mapSummary})
        elif request.GET['utilType'] == 'report_charts':
            saved_chart_objects = ChartImage.objects.filter(project = Project.objects.get(pk=request.GET['projectId']), type='User')
            saved_charts = []
            for object in saved_chart_objects:
                saved_charts.append(object.name.encode('utf8'))
            return render_to_response('savedChartsInline.html',{'saved_charts':saved_charts})
        elif request.GET['utilType'] == 'recalcZones':
            projectObj = Project.objects.get(pk=request.GET['projectId'])
            diObjects = Test.objects.filter(project=projectObj)
            for di in diObjects: 
                found_zones = Zone.objects.filter(project=di.project, floor=di.floor, zone_map__intersects=di.location)
                di.zone.clear() #clear current m2m relationship and reassign
                for zone in found_zones:
                    if zone not in di.zone.all():
                        di.zone.add(zone)
                        di.save()
            return HttpResponse('Success')
           
        elif request.GET['utilType'] == 'dates':
            projectObj = Project.objects.get(pk=request.GET['projectId'])
            sd = projectObj.start_date
            sd = datetime.datetime.combine(sd, datetime.time())
            start_date = timegm(sd.utctimetuple())
            ed = projectObj.end_date
            ed = datetime.datetime.combine(ed, datetime.time())
            end_date = timegm(ed.utctimetuple())
            return HttpResponse(simplejson.dumps({'start_date': start_date * 1000, 'end_date': end_date * 1000}), mimetype="application/json")
        elif request.GET['utilType'] == 'tz':
            projectObj = Project.objects.get(pk=request.GET['projectId'])
            time_zone = projectObj.timezone
            return HttpResponse(time_zone)
        elif request.GET['utilType'] == 'ieq_model':
            ieqModelFD = IeqModelFormDrop(auto_id="id_ieqModel_%s")
            return render_to_response('ieqModelInline.html',{'ieq_model': ieqModelFD})
        elif request.GET['utilType'] == 'flr_model':
            flr_model = make_floorForm(request.GET['projectId'])
            return render_to_response('floorInline.html',{'flr_model': flr_model})
        elif request.GET['utilType'] == 'addZone':
            zoneForm = make_zoneForm(request.GET['projectId'], False)
            return render_to_response('zonePopup.html',{'zoneForm':zoneForm})
        elif request.GET['utilType'] == 'addModel':
            modelForm = make_modelForm(False)
            return render_to_response('modelPopup.html',{'modelForm':modelForm})
        elif request.GET['utilType'] == 'deviceInstanceSummary':
            projectKey = request.GET['projectId']
            deviceFormSet = modelformset_factory(Test, extra=0)
            test_objects = Test.objects.filter(zone__project=projectKey)
            deviceFS = deviceFormSet(queryset=test_objects)
            flr_model = make_floorForm(projectKey)
            return render_to_response('deviceISPopup.html',{'deviceFS':deviceFS, 'flr_model':flr_model, 'projectId':projectKey})
        elif request.GET['utilType'] == 'deviceInstanceFlrChange':
            info = []
            projectKey = request.GET['projectId']
            map_obj = Map.objects.get(floor=Floor.objects.get(pk=request.GET['floorId']), project=Project.objects.get(pk=projectKey))
            test_objects = Test.objects.filter(zone__project=projectKey, floor=request.GET['floorId'])
            for test_object in test_objects: 
                if test_object.location:
                    if test_object.device.type == 'Acoustics':
                        color = 'blue'
                    elif test_object.device.type == 'Cart':
                        color = 'green'
                    elif test_object.device.type == 'ICM':
                        color = '#FF00FF'
                    elif test_object.device.type == 'Plenum mote':
                        color = 'orange'
                    else:
                        color = 'red'
                    try:
                        info.append((test_object.location, {
                            'html': repr(test_object.device).replace('<', '').replace('>', ''),
                            'style': {
                                'fill_color': color,
                                'stroke_color': color,
                            },
                        }))
                    except:
                        continue
     
            map = InfoMap(info, {
                'layers': ['image_layer'],
                'map_div_style': {'width':'100%', 'height':'450px'},
                 'mapOptions':({
                       'max_extent': [map_obj.left_extent,map_obj.bottom_extent,map_obj.right_extent,map_obj.top_extent],
                       'max_resolution': map_obj.resolution,
                       'num_zoom_levels': map_obj.zoom_levels,
            })})
            
            zone_objects = Zone.objects.filter(project=projectKey, floor=request.GET['floorId'])
            for i in xrange(len(zone_objects)):
                if zone_objects[i].zone_map:
                    color = choice(colormap)
                    info.append((zone_objects[i].zone_map, {
                        'html': 'Zone: ' + zone_objects[i].name,
                        'style': {
                            'fill_color': color,
                            'stroke_color': color,
                            'stroke_opacity': 0.7,
                            #'stroke_width': 1,
                            'fill_opacity': 0.15,
                        },
                    }))
     
            map = InfoMap(info, {
                'layers': ['image_layer'],
                'map_div_style': {'width':'100%', 'height':'450px'},
                 'mapOptions':({
                       'max_extent': [map_obj.left_extent,map_obj.bottom_extent,map_obj.right_extent,map_obj.top_extent],
                       'max_resolution': map_obj.resolution,
                       'num_zoom_levels': map_obj.zoom_levels,
            })})
            return render_to_response("map_inline.html", {"map": map, 'type': 'deviceSummary'})
        elif request.GET['utilType'] == 'zoneSummary':
            projectKey = request.GET['projectId']
            flr_model = make_floorForm(projectKey)
            return render_to_response('zoneSummaryPopup.html',{'flr_model':flr_model, 'projectId':projectKey})
        elif request.GET['utilType'] == 'zoneFlrChange':
            info = []
            projectKey = request.GET['projectId']
            map_obj = Map.objects.get(floor=Floor.objects.get(pk=request.GET['floorId']), project=Project.objects.get(pk=projectKey))
            zone_objects = Zone.objects.filter(project=projectKey, floor=request.GET['floorId'])
            for i in xrange(len(zone_objects)):
                if zone_objects[i].zone_map:
                    color = choice(colormap)
                    info.append((zone_objects[i].zone_map, {
                        'html': 'Zone: ' + zone_objects[i].name,
                        'style': {
                            'fill_color': color,
                            'stroke_color': color,
                            'stroke_opacity': 0.7,
                            #'stroke_width': 1,
                            'fill_opacity': 0.15,
                        },
                    }))
     
            map = InfoMap(info, {
                'layers': ['image_layer'],
                'map_div_style': {'width':'100%', 'height':'450px'},
                 'mapOptions':({
                       'max_extent': [map_obj.left_extent,map_obj.bottom_extent,map_obj.right_extent,map_obj.top_extent],
                       'max_resolution': map_obj.resolution,
                       'num_zoom_levels': map_obj.zoom_levels,
            })})
            return render_to_response("map_inline.html", {"map": map, 'type': 'zoneSummary'})
    else: #POST type
        if 'iaq_weight' in request.POST: #handle adding a new model
            modelForm = make_modelForm(request.POST)
            if modelForm.is_valid():
                new_object = modelForm.save()
            else:
                new_object = modelForm
            pk_value = new_object._get_pk_val()
            return HttpResponse(
                '<!DOCTYPE html><html><head><title></title></head><body>'
                '<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
                # escape() calls force_unicode.
                (escape(pk_value), escapejs(new_object)))
        elif 'floor' in request.POST: #handle zone form
            zoneForm = make_zoneForm(False, request.POST)
            if zoneForm.is_valid():
                new_object = zoneForm.save()
            else:
                new_object = zoneForm
            pk_value = new_object._get_pk_val()
            return HttpResponse(
                '<!DOCTYPE html><html><head><title></title></head><body>'
                '<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
                # escape() calls force_unicode.
                (escape(pk_value), escapejs(new_object)))
        elif len(request.FILES) > 0: #chart image for map type charts
            imageurl = 'http://smap.cbe.berkeley.edu/static/userData/temp.png'
            map= 'true'
            if request.POST['pmp_category'] == 'comfort':
                cat = 'Thermal Comfort'
            elif request.POST['pmp_category'] == 'lighting':
                cat = 'Lighting'
            elif request.POST['pmp_category'] == 'acoustics':
                cat = 'Acoustics'
            else:
                cat = 'IAQ'
            try: #see if an image with same name exists
                a = ChartImage.objects.get(project=Project.objects.get(pk=request.POST['projectId']), name=request.POST['name'])
            except: #new image
                a = ChartImage(project=Project.objects.get(pk=request.POST['projectId']),image_url=imageurl, pmp_category=cat, type=request.POST['mapSummary'])
            chartForm = ChartImageForm(request.POST, request.FILES, instance=a, auto_id="id_image_%s")
            if chartForm.is_valid():
                chartForm.save()
                if map:
                    chartImage_obj = ChartImage.objects.latest('id')
                    newChartForm = ChartImageForm(instance=chartImage_obj)
                    correctedForm = newChartForm.save(commit=False)
                    correctedForm.image_url = chartImage_obj.map_image.url
                    correctedForm.save()
                success = 'Saved successfully'
            else:
                success = 'Check form for errors'
            return render_to_response('chartImageInline.html', {'chart_image_form':chartForm, 'saveStatus':success, 'map':map})
        else: #POST with jsondata
            post_data = simplejson.loads(request.body)
            if 'utilType' in post_data: #save charts
                chartForm = ChartImageForm(post_data['chartImageForm'], auto_id="id_image_%s")
                chartForm.is_valid()
                map= 'false'
                image = post_data['image']
                imgstr = re.search(r'base64,(.*)', image).group(1)
                imagefile = '/opt/bpe_toolkit/staticStore/userData/%s.png' % post_data['name']
                imageurl = 'http://smap.cbe.berkeley.edu/static/userData/%s.png' % post_data['name']
                output = open(imagefile, 'wb')
                output.write(imgstr.decode('base64'))
                output.close()
                if post_data['pmp_category'] == 'comfort':
                    cat = 'Thermal Comfort'
                elif post_data['pmp_category'] == 'lighting':
                    cat = 'Lighting'
                elif post_data['pmp_category'] == 'acoustics':
                    cat = 'Acoustics'
                else:
                    cat = 'IAQ'
                try: #see if an image with same name exists
                    a = ChartImage.objects.get(project=Project.objects.get(pk=post_data['projectId']), name=post_data['name'])
                except: #new image
                    a = ChartImage(project=Project.objects.get(pk=post_data['projectId']),image_url=imageurl, pmp_category=cat, type='User', legend=post_data['legend'])
                chartForm = ChartImageForm(post_data['chartImageForm'], instance=a, auto_id="id_image_%s")
                if chartForm.is_valid():
                    chartForm.save()
                    success = 'Saved successfully'
                else:
                    success = 'Check form for errors'
                return render_to_response('chartImageInline.html', {'chart_image_form':chartForm, 'saveStatus':success, 'map':map})
            elif 'selected_charts' in post_data: #handle deleting saved charts from the report page
                selected_charts = post_data['selected_charts']
                for chart in selected_charts:
                    chart_object = ChartImage.objects.get(project = Project.objects.get(pk=post_data['projectId']), type="User", name=chart)
                    chart_object.delete()
                saved_chart_objects = ChartImage.objects.filter(project = Project.objects.get(pk=post_data['projectId']), type='User')
                saved_charts = []
                for object in saved_chart_objects:
                    saved_charts.append(object.name.encode('utf8'))
                return render_to_response('savedChartsInline.html',{'saved_charts':saved_charts})
                
            elif 'ieq_model' in post_data: #handle showing the correct dropdowns for ieq_model when it is saved
                ieqModelFD = IeqModelFormDrop(post_data['ieq_model_form'], auto_id="id_ieqModel_%s")
                ieqDataFD = make_ieqData_formd(int(post_data['ieq_model']),post_data['ieq_category'], post_data['projectId'])
                return render_to_response('ieqModelInline.html',{'ieq_model': ieqModelFD, 'ieq_data': ieqDataFD})
            else: #smap trending csv export
                try:
                    uuids = post_data['uuids']
                    allPoints = False
                except:
                    projectQ = Project.objects.get(pk=post_data['projectId'])
                    if projectQ.name == 'bancroft':
                        queryA = 'Path like \"/Bancroft/doe%\" or Metadata/Extra/Project = \"bancroft\"' 
                    elif projectQ.name == 'sdh':
                        queryA = 'Path like \"/Siemens/SDH%\" or Metadata/Extra/Project = \"sdh\"' 
                    else:
                        queryA = 'Metadata/Extra/Project = \"' + projectQ.name + '\"'
                    allPoints = True
                c = smap.archiver.client.SmapClient(base='http://new.openbms.org/backend', key=['WE4iJWG7k575AluJ9RJyAZs25UO72Xu0b4RA','SA2nYWuHrJxmPNK96pdLKhnSSYQSPdALkvnA'])
                if allPoints == False:
                    queryS = 'apply window(first, field=\"minute\", width=' + str(post_data['interval']) + ') to data in (' + str(post_data['start_date']) + ',' + str(post_data['end_date']) + ') limit 100000000 where uuid = '
                    i = 0
                    for streamid in uuids:
                        if i == 0:
                            queryS += '\"' + streamid + '\"'
                            i += 1
                        else:
                            queryS += ' or uuid = \"' + streamid + '\"'
                            i += 1
                else:
                    #queryS = 'apply interpolate(field=\"minute\", width=' + str(post_data['interval']) + ', max_time_delta=60) to data in (' + str(post_data['start_date']) + ',' + str(post_data['end_date']) + ') limit 100000000 where ' + queryA 
                    queryS = 'apply window(first, field=\"minute\", width=' + str(post_data['interval']) + ')to data in (' + str(post_data['start_date']) + ',' + str(post_data['end_date']) + ') limit 100000000 where ' + queryA
                #return HttpResponse(queryS)
                data = c.query(queryS)
                #return HttpResponse(simplejson.dumps({'data':data,'query':queryS}),mimetype="application/json")
                f = open('/opt/bpe_toolkit/staticStore/userData/smapTrendExport.csv', 'w')    
                writer = csv.writer(f)
                headings = ['datetime']
                allData = []
                for stream_data in data:
                    try:
                        for obj in uuids:
                            if uuids[obj]['Path'] == stream_data['Path']:
                                headings.append(uuids[obj]['Metadata']['Toolkit']['name'])
                    except:
                        try:
                            headings.append(stream_data['Path'])
                        except:
                            pass
                    allData.append(np.array(stream_data['Readings'])) #interpolate to interval time and average x number of samples
                #return HttpResponse(len(allData))
                n_headings = ['datetime']
                n_allData = []
                success_c = 0
                #n_allData = [allData[0][:,0]]
                for j in xrange(len(allData)):
                    try:
                        n_allData.append(allData[j][:,1])
                        n_headings.append(headings[j+1])
                        success_c = j
                    except:
                        pass
                writer.writerow(n_headings)
                transposed = zip(*n_allData)
                #return HttpResponse(transposed)
                dt_format = '%Y-%m-%d %H:%M:%S'
                for i in xrange(len(transposed)):
                    row = [datetime.datetime.fromtimestamp(allData[success_c][i][0]/1000).strftime(dt_format)]
                    row.extend(transposed[i])
                    writer.writerow(row)
        
                f.close()
                return HttpResponse('success')
    
@login_required
def configFileLoad(request):
    configFileName = ConfigFile.objects.get(pk=request.GET['name'])
    try:
        treeJSON = open('/opt/bpe_toolkit/staticStore/userData/' + str(configFileName) + '_' + str(request.GET['name']) + '.json', 'r').read()
    except:
        treeJSON = open('/opt/bpe_toolkit/staticStore/userData/' + str(configFileName) + '.json', 'r').read()
    return HttpResponse(treeJSON,mimetype="application/json")

@login_required
def sensors(request):
    user = request.user   
    if request.method == 'POST':
        show = True
        if 'select' in request.POST:
            projectKey = request.POST['projectId']
            project = Project.objects.get(pk=projectKey)
            sensorFormSet = inlineformset_factory(Project, Sensor, form=make_sensor_form(projectKey), extra=1, can_delete=True,)
            sensorFS = sensorFormSet(instance=project)
            if len(sensorFS) > 1: # if there is already data, just render it
                return render_to_response('display_inline.html',{'user': user,'sensorFS': sensorFS, 'show':show, 'projectKey':projectKey})
            else: # if there isn't data, then prefill a formset with path and uuid for that project
                if request.POST['select'] == 'blank' or request.POST['select'] == 'default':
                    c = smap.archiver.client.SmapClient(base='http://new.openbms.org/backend', key=['WE4iJWG7k575AluJ9RJyAZs25UO72Xu0b4RA','SA2nYWuHrJxmPNK96pdLKhnSSYQSPdALkvnA'])
                    projectName = str(project)
                    uuids = c.query('select distinct uuid where Path like \'/%s/' % projectName + '%\'')
                    initialData = []
                    for uuid in uuids:
                        path = c.query('select distinct Path where uuid = \'%s\'' % uuid)
                        #temporary code for nsa hobos
                        #name = path[0].split('/')[2]
                        #hobo = name.split('_')
                        #hobo_sn = hobo[0]
                        #if len(hobo) == 2:
                        #    sensor_type = hobo[1]
                        #    sensor_height = -10
                        #else:
                        #    sensor_type = hobo[2]
                        #    sensor_height = hobo[1]
                        #if sensor_type == 'rh':
                        #    type = 'Relative humidity'
                        #else:
                        #    type = 'Thermistor'
                        #try:
                        #    device = Device.objects.get(name='HOBO ' + hobo_sn)
                        #except:
                        #    if len(hobo) == 2:
                        #        device = Device(name='HOBO ' + hobo_sn, type='Plenum mote')
                        #    else:
                        #        device = Device(name='HOBO ' + hobo_sn, type='Fixed pole')
                        #    device.save()
#                        initialData.append({'uuid':uuid, 'path':path[0], 'device':device.pk,'name':name,'sensor_type':type, 'pmp_category':'Thermal Comfort', 'sensor_height':sensor_height})
                        initialData.append({'uuid':uuid, 'path':path[0]})
                    initialData = sorted(initialData, key = itemgetter('path'))
                    if request.POST['select'] == 'default':
                        default_sensors = [[["name","cart_ceiling_irt"],["device","1"],["sensor_type","IRT"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","cart_04\"_ceiling"],["device","1"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","glb_icm03"],["device","21"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm03"],["device","21"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","glb_icm04"],["device","22"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm04"],["device","22"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm11"],["device","31"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","rh_icm11"],["device","31"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","glb_icm11"],["device","31"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm11"],["device","31"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","anem_icm02"],["device","20"],["sensor_type","Anemometer"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm02"],["device","20"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","glb_icm02"],["device","20"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm02"],["device","20"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm05"],["device","24"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","illum_icm05"],["device","24"],["sensor_type","Illuminance"],["pmp_category","Lighting"],["sensor_height",""]],
                            [["name","glb_icm05"],["device","24"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm05"],["device","24"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","glb_icm06"],["device","25"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm06"],["device","25"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm06"],["device","25"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm06"],["device","25"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","pressure"],["device","1"],["sensor_type","Pressure"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","sat"],["device","1"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","glb_icm07"],["device","27"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm07"],["device","27"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm07"],["device","27"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm07"],["device","27"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","rh_icm08"],["device","28"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","illum_icm08"],["device","28"],["sensor_type","Illuminance"],["pmp_category","Lighting"],["sensor_height",""]],
                            [["name","glb_icm08"],["device","28"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm08"],["device","28"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm09"],["device","29"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","illum_icm09"],["device","29"],["sensor_type","Illuminance"],["pmp_category","Lighting"],["sensor_height",""]],
                            [["name","glb_icm09"],["device","29"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm09"],["device","29"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","glb_icm10"],["device","30"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm10"],["device","30"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm10"],["device","30"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","illum_icm10"],["device","30"],["sensor_type","Illuminance"],["pmp_category","Lighting"],["sensor_height",""]],
                            [["name","anem_icm12"],["device","32"],["sensor_type","Anemometer"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm12"],["device","32"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","cart_67\""],["device","1"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","cart_24\""],["device","1"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","glb_icm12"],["device","32"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm12"],["device","32"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","sound_level"],["device","36"],["sensor_type","Sound level"],["pmp_category","Acoustics"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","glb_icm13"],["device","33"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm13"],["device","33"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm13"],["device","33"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm13"],["device","33"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","anem_icm15"],["device","35"],["sensor_type","Anemometer"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm15"],["device","35"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","glb_icm15"],["device","35"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm15"],["device","35"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","anem_icm14"],["device","34"],["sensor_type","Anemometer"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm14"],["device","34"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","glb_icm14"],["device","34"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm14"],["device","34"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","plenum_01"],["device","10"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_02"],["device","39"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","cart_48\""],["device","1"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","cart_04\""],["device","1"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","plenum_03"],["device","40"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_04"],["device","41"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_05"],["device","42"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_06"],["device","43"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_07"],["device","44"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_08"],["device","45"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_09"],["device","46"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_10"],["device","47"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_11"],["device","48"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_12"],["device","49"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","cart_floor_irt"],["device","1"],["sensor_type","IRT"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","cart_10\""],["device","1"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","plenum_13"],["device","50"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_14"],["device","51"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_15"],["device","52"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_16"],["device","53"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_17"],["device","54"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","plenum_18"],["device","55"],["sensor_type","Mote thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name",""],["device",""],["sensor_type",""],["pmp_category",""],["sensor_height",""]],
                            [["name","glb_icm01"],["device","19"],["sensor_type","Globe temperature (pp-ball)"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","dbt_icm01"],["device","19"],["sensor_type","Thermistor"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","anem_icm01"],["device","19"],["sensor_type","Anemometer"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm01"],["device","19"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","rh_icm04"],["device","22"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm04"],["device","22"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]],
                            [["name","rh_icm03"],["device","21"],["sensor_type","Relative humidity"],["pmp_category","Thermal Comfort"],["sensor_height",""]],
                            [["name","co2_icm03"],["device","21"],["sensor_type","CO2"],["pmp_category","IAQ"],["sensor_height",""]]]


                        for i in xrange(len(initialData)):
                            for column in default_sensors[i]:
                                initialData[i][column[0]] = column[1]
                        #return HttpResponse(simplejson.dumps(initialData),mimetype="application/json")
                        
                    sensorFormSet = inlineformset_factory(Project, Sensor, form=make_sensor_form(projectKey), extra=len(initialData), can_delete=True)
                    sensorFS = sensorFormSet(initial=initialData)
                    return render_to_response('display_inline.html',{'user': user,'sensorFS': sensorFS, 'show':show, 'projectKey':projectKey})
                else:
                    return render_to_response('display_inline.html',{'user': user, 'projectKey':projectKey})
        else:
            projectKey = request.POST['projectId']
            project = Project.objects.get(pk=projectKey)
            sensorFormSet = inlineformset_factory(Project, Sensor, form=make_sensor_form(projectKey), extra=1, can_delete=True,)
            sensorFS = sensorFormSet(request.POST, instance=project)
            if sensorFS.is_valid():
                sensorFS.save()
                sensorFS = sensorFormSet(instance=project) #repost the instance after saving
                saveStatus = "Saved successfully"
            else:
                saveStatus = "Check form for errors"
            return render_to_response('display_inline.html',{'user': user,'sensorFS': sensorFS, 'show':show, 'projectKey':projectKey, 'saveStatus':saveStatus})
    else:
        userI = User.objects.get(username=user)
        groupL = userI.groups.all().values_list('pk', flat=True)
        projectF = make_project_form(groupL)
        show = False
        
        c = {'user': user,
             'projectF': projectF,
             'show': show,
             }
        return render_to_response('sensors.html',c)

@login_required
def deviceInstance(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)   
    if request.method == 'POST':
        if 'select' in request.POST:
            projectKey = request.POST['projectId']
            deviceFD = make_deviceFD(projectKey, False)
            return render_to_response('deviceInstanceInline.html',{'deviceFD': deviceFD})
        else:
            post_data = simplejson.loads(request.body)
            projectKey = post_data['projectId']
            #activate the correct timezone so that start/end time is correct
            time_zone = tz.gettz(Project.objects.get(pk=projectKey).timezone)
            timezone.activate(time_zone)
            if post_data['select'] == 'device':
                deviceFD = make_deviceFD(projectKey, post_data['deviceForm'])
                deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], False, False)
                return render_to_response('deviceInstanceInline.html',{'deviceInstanceFD': deviceInstanceFD, 'deviceFD': deviceFD})
            elif post_data['select'] == 'deviceInstance':
                deviceFD = make_deviceFD(projectKey, post_data['deviceForm'])
                deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], post_data['deviceInstanceForm'], False)
                deviceInstanceF = make_deviceInstance_form(post_data['deviceInstanceId'], False, False, projectKey)
                manualEntryF = make_manualEntry_form(post_data['deviceId'], post_data['deviceInstanceId'])
                return render_to_response('deviceInstanceInline.html',{'deviceInstanceF': deviceInstanceF, 'deviceInstanceFD': deviceInstanceFD, 'deviceFD': deviceFD, 'manualEntryF':manualEntryF})
            elif post_data['select'] == 'add':
                deviceFD = make_deviceFD(projectKey, post_data['deviceForm'])
                deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], False, False)
                deviceInstanceF = make_deviceInstance_form(False, False, False, projectKey)
                device_obj = Device.objects.get(pk=post_data['deviceId'])
                manualEntryF = make_manualEntry_form(post_data['deviceId'])
                return render_to_response('deviceInstanceInline.html',{'deviceInstanceF': deviceInstanceF, 'deviceInstanceFD': deviceInstanceFD, 'deviceFD': deviceFD, 'manualEntryF':manualEntryF})
            elif post_data['select'] == 'floorChange':
                floorId = post_data['floorId']
                deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], post_data['deviceInstanceForm'], False)
                deviceFD = make_deviceFD(projectKey, post_data['deviceForm'])
                deviceInstanceF = make_deviceInstance_form(post_data['deviceInstanceId'], post_data['deviceIF'], False, projectKey, floorId)
                device_obj = Device.objects.get(pk=post_data['deviceId'])
                manualEntryF = make_manualEntry_form(post_data['deviceId'], post_data['deviceInstanceId'])
                return render_to_response('deviceInstanceInline.html',{'deviceInstanceF': deviceInstanceF, 'deviceInstanceFD': deviceInstanceFD, 'deviceFD': deviceFD, 'manualEntryF':manualEntryF})
            elif post_data['select'] == 'submitInstance':
                deviceFD = make_deviceFD(projectKey, post_data['deviceForm'])
                a = Test(device=Device.objects.get(pk=post_data['deviceId']), project=Project.objects.get(pk=projectKey))
                deviceInstanceF = make_deviceInstance_form(post_data['deviceInstanceId'], post_data['deviceIF'], a, projectKey)
                device_obj = Device.objects.get(pk=post_data['deviceId'])
                if deviceInstanceF.is_valid():
                    try:
                        #find all zones that this point falls in (this could be more than one zone because of overlapping zones)
                        found_zones = Zone.objects.filter(project=projectKey, floor=deviceInstanceF.cleaned_data['floor'], zone_map__intersects=deviceInstanceF.cleaned_data['location'])
                        corrected_di = deviceInstanceF.save() #must save before you can use m2m relationship
                        #add each found_zone to the m2m zone object in the test object
                        for found_zone in found_zones:
                            corrected_di.zone.add(found_zone)
                        corrected_di.save()
                        if post_data['deviceInstanceId'] != "":
                            deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], post_data['deviceInstanceForm'], False)
                            test_obj = Test.objects.get(pk=post_data['deviceInstanceId'])
                        else:
                            newdevicea = Test.objects.latest('id')
                            test_obj = newdevicea
                            deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], False, newdevicea)
                        saveStatus = "Saved successfully"  
                    except:
                        deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], post_data['deviceInstanceForm'], False)
                        saveStatus = "The location you chose does not fall in an existing zone. Make sure you have a zone defined for this location."
                        test_obj = False
                    #deal with manual entries
                    if test_obj:
                        if device_obj.name == 'HDR camera':
                            try:
                                b = HdrTest.objects.get(test=test_obj)
                            except:
                                b = HdrTest(test=test_obj)
                            manualEntryF = HdrTestForm(post_data['manualEntryF'], instance=b)
                        elif device_obj.name == 'IAQ meter':
                            try:
                                b = IaqTest.objects.get(test=test_obj)
                            except:
                                b = IaqTest(test=test_obj)
                            manualEntryF = IaqTestForm(post_data['manualEntryF'], instance=b)
                        elif device_obj.name == 'Sound level meter':
                            try:
                                b = AcousticsTest.objects.get(test=test_obj)
                            except:
                                b = AcousticsTest(test=test_obj)
                            manualEntryF = AcousticsTestForm(post_data['manualEntryF'], instance=b)
                        else:
                            manualEntryF = False
                        if manualEntryF:
                            if manualEntryF.is_valid():
                                manualEntryF.save()
                            else:
                                saveStatus = "Check form for errors"
                    else:
                        manualEntryF = False
                else:
                    deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], post_data['deviceInstanceForm'], False)
                    saveStatus = "Check form for errors"
                    manualEntryF = False    
                return render_to_response('deviceInstanceInline.html',{'deviceInstanceF': deviceInstanceF, 'deviceInstanceFD': deviceInstanceFD, 'deviceFD': deviceFD, 'saveStatus': saveStatus, 'submit':True, 'manualEntryF':manualEntryF})
            elif post_data['select'] == 'deleteInstance':
                deviceFD = make_deviceFD(projectKey, post_data['deviceForm'])
                deviceInstanceFD = make_deviceIFD(projectKey, post_data['deviceId'], False, False)
                try:
                    deviceInstance = Test.objects.get(pk=post_data['deviceInstanceId'])
                    deviceInstance.delete()
                    saveStatus = "Deleted successfully" #this doesn't actually show up, oh well...
                except:
                    saveStatus = "Problem deleting device instance"
                return render_to_response('deviceInstanceInline.html',{'deviceInstanceFD': deviceInstanceFD, 'deviceFD': deviceFD, 'saveStatus': saveStatus})
    c = {'user': user,
         'projectF': projectF,
         }
    return render_to_response('deviceInstance.html',c)

@login_required
def zones(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)   
    if request.method == 'POST':
        if 'select' in request.POST:
            projectKey = request.POST['projectId']
            zoneFD = make_zoneFD(projectKey, False, False)
            return render_to_response('zonesInline.html',{'zoneFD': zoneFD})
        else:
            post_data = simplejson.loads(request.body)
            projectKey = post_data['projectId']
            if post_data['select'] == 'zoneInstance':
                if post_data['zone_categories']:
                    zone_categories = post_data['zone_categories']
                else:
                    zone_categories = []
                zoneFD = make_zoneFD(projectKey, post_data['zoneInstanceForm'], False)
                zoneInstance = make_zoneFormInstance(False, post_data['zoneInstanceId'], False, projectKey, False, zone_categories)
                return render_to_response('zonesInline.html',{'zoneFD': zoneFD, 'zoneInstance': zoneInstance})
            elif post_data['select'] == 'add':
                zone_categories = post_data['zone_categories']
                zoneFD = make_zoneFD(projectKey,False, False)
                zoneInstance = make_zoneFormInstance(post_data['zoneInstanceForm'], False, False, projectKey, False, zone_categories)
                return render_to_response('zonesInline.html',{'zoneFD': zoneFD, 'zoneInstance': zoneInstance})
            elif post_data['select'] == 'floorChange':
                zone_categories = post_data['zone_categories']
                floorId = post_data['floorId']
                zoneFD = make_zoneFD(projectKey, post_data['zoneInstanceForm'], False)
                zoneInstance = make_zoneFormInstance(post_data['zoneIF'], post_data['zoneInstanceId'], False, projectKey, floorId, zone_categories)
                return render_to_response('zonesInline.html',{'zoneInstance': zoneInstance, 'zoneFD': zoneFD})
            elif post_data['select'] == 'submitInstance':
                zone_categories = post_data['zone_categories']
                a = Zone(project=Project.objects.get(pk=projectKey))
                zoneInstance = make_zoneFormInstance(post_data['zoneIF'], post_data['zoneInstanceId'], a, projectKey, False, zone_categories)
                if zoneInstance.is_valid():
                    zoneInstance.save()
                    if post_data['zoneInstanceId'] != "":
                        zoneFD = make_zoneFD(projectKey, post_data['zoneInstanceForm'], False)
                    else:
                        newzonea = Zone.objects.latest('id')
                        zoneFD = make_zoneFD(projectKey, False, newzonea)
                    saveStatus = "Saved successfully"
                else:
                    zoneFD = make_zoneFD(projectKey, post_data['zoneInstanceForm'], False)
                    saveStatus = "Check form for errors"
                return render_to_response('zonesInline.html',{'zoneInstance': zoneInstance, 'zoneFD': zoneFD, 'saveStatus': saveStatus, 'submit':True})
            elif post_data['select'] == 'deleteZone':
                zoneFD = make_zoneFD(projectKey, False, False)
                try:
                    zoneInstance = Zone.objects.get(pk=post_data['zoneInstanceId'])
                    zoneInstance.delete()
                    saveStatus = "Deleted successfully" #this doesn't actually show up, oh well...
                except:
                    saveStatus = "Problem deleting zone"
                return render_to_response('zonesInline.html',{'zoneFD': zoneFD, 'saveStatus': saveStatus})
    c = {'user': user,
         'projectF': projectF,
         }
    return render_to_response('zones.html',c)

@login_required
def maps(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)   
    if request.method == 'POST':
        if 'select' in request.POST:
            projectKey = request.POST['projectId']
            mapFD = make_mapFD(projectKey, False, False)
            return render_to_response('mapsInline.html',{'mapFD': mapFD})
        elif 'floor' in request.POST: #submit
            projectKey = request.POST['projectId']
            try:
                Map.objects.get(project=Project.objects.get(pk=projectKey),floor=Floor.objects.get(pk=request.POST['floor']))
                existingMap = True
            except:
                existingMap = False
            a = Map(project=Project.objects.get(pk=projectKey))
            mapInstance = make_mapFormInstance(request.POST, request.POST['mapInstanceId'], a, projectKey, request.FILES)
            if existingMap and request.POST['mapInstanceId'] == '':
                saveStatus = "There is already a map object for this floor, select from the dropdown if you want to edit that map"
                if request.POST['mapInstanceId'] != "":
                    newmapa = Map.objects.get(pk=request.POST['mapInstanceId'])
                    mapFD = make_mapFD(projectKey, False, newmapa)
                else:
                    mapFD = make_mapFD(projectKey, False, False)
            else:
                if mapInstance.is_valid():
                    mapInstance.save()
                    if request.POST['mapInstanceId'] != "":
                        newmapa = Map.objects.get(pk=request.POST['mapInstanceId'])
                        mapFD = make_mapFD(projectKey, False, newmapa)
                    else:
                        newmapa = Map.objects.latest('id')
                        mapFD = make_mapFD(projectKey, False, newmapa)
                    filePath = settings.MEDIA_ROOT + newmapa.map_tiler_zip_file.name
                    mapDir = settings.MEDIA_ROOT + projectKey + '/' + request.POST['floor']
                    saveStatus = "Saved successfully"
                    if 'unzip' in request.POST:    
                        try:
                            if not os.path.exists(mapDir):
                                os.makedirs(mapDir)
                            zipMap = zipfile.ZipFile(filePath, 'r')
                            zipMap.extractall(mapDir)
                            newMapInstance = make_mapFormInstance(False, False, newmapa, projectKey, False)
                            cMapInstance = newMapInstance.save(commit=False)
                            if cMapInstance.left_extent == None or cMapInstance.right_extent == None or cMapInstance.bottom_extent == None or cMapInstance.top_extent == None or cMapInstance.resolution == None or cMapInstance.zoom_levels == None: #find the bounds, resolution, maxlevels from the openlayer.html file    
                                try:
                                    openlayers_fp = open(mapDir + '/openlayers.html', 'r')
                                    fp_contents = openlayers_fp.read()
                                    bounds = re.search('OpenLayers.Bounds\( (.*)\)',fp_contents).group(1).replace(' ','').split(',')
                                    maxRes = re.search('maxResolution: (.*),', fp_contents).group(1)
                                    numZoom = re.search('numZoomLevels: (.*)', fp_contents).group(1)
                                    cMapInstance.left_extent = bounds[0]
                                    cMapInstance.bottom_extent = bounds[1]
                                    cMapInstance.right_extent = bounds[2]
                                    cMapInstance.top_extent = bounds[3]
                                    cMapInstance.zoom_levels = int(float(numZoom))
                                    cMapInstance.resolution = int(float(maxRes))
                                    try:
                                        cMapInstance.save()
                                        mapInstance = make_mapFormInstance(False, False, cMapInstance, projectKey, False)
                                        saveStatus = "Saved successfully"
                                    except:
                                        saveStatus = "Check form for errors"
                                except:
                                    saveStatus = "There was a problem reading the file, you will need to enter the extents, resolution, and zoom levels manually"
                        except:
                            saveStatus = "There was a problem reading the file, did you specify a file? Uncheck \"Unzip files\" if you do not intend to upload a map"
                else:
                    if request.POST['mapInstanceId'] != "":
                        newmapa = Map.objects.get(pk=request.POST['mapInstanceId'])
                        mapFD = make_mapFD(projectKey, False, newmapa)
                    else:
                        mapFD = make_mapFD(projectKey, False, False)
                    saveStatus = "Check form for errors"
            return render_to_response('mapsInline.html',{'mapInstance': mapInstance, 'mapFD': mapFD, 'saveStatus': saveStatus, 'submit':True})
        else:
            post_data = simplejson.loads(request.body)
            projectKey = post_data['projectId']
            if post_data['select'] == 'mapInstance':
                mapFD = make_mapFD(projectKey, post_data['mapInstanceForm'], False)
                mapInstance = make_mapFormInstance(False, post_data['mapInstanceId'], False, projectKey)
                return render_to_response('mapsInline.html',{'mapFD': mapFD, 'mapInstance': mapInstance})
            elif post_data['select'] == 'add':
                mapFD = make_mapFD(projectKey,False, False)
                mapInstance = make_mapFormInstance(False, False, False, projectKey)
                return render_to_response('mapsInline.html',{'mapFD': mapFD, 'mapInstance': mapInstance})
            elif post_data['select'] == 'deleteMap':
                mapFD = make_mapFD(projectKey, False, False)
                try:
                    mapInstance = Map.objects.get(pk=post_data['mapInstanceId'])
                    mapInstance.delete()
                    saveStatus = "Deleted successfully" #this doesn't actually show up, oh well...
                except:
                    saveStatus = "Problem deleting map"
                return render_to_response('mapsInline.html',{'mapFD': mapFD, 'saveStatus': saveStatus})
    c = {'user': user,
         'projectF': projectF,
         }
    return render_to_response('maps.html',c)

@login_required
def scorecard(request):
    log = False
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)
    ieqModelFD = IeqModelFormDrop(auto_id="id_ieqModel_%s")
    if request.method == 'POST':
        post_data = simplejson.loads(request.body)
        projectId = int(post_data['projectId'])
        project_obj = Project.objects.get(pk=projectId)
        ieq_model = int(post_data['ieq_model']['name'])
        ieq_model_obj = IeqModel.objects.get(pk=ieq_model)
        ieq_weights = []
        st_weights = []
        eqi_alert = False #alert user if weightings have been altered
        bqi_alert = False
        #get only the ieq categories that have been saved for this project
        ieq_data_categories = IeqData.objects.filter(project=project_obj).filter(ieq_space__model=ieq_model_obj).distinct().values_list('ieq_category', flat=True)
        if len(ieq_data_categories) == 4: #make sure there is data for all 4 categories
            for category in ieq_data_categories:
                if category == 'Thermal Comfort':
                    ieq_weights.append(float(ieq_model_obj.tc_weight))
                elif category == 'Lighting':
                    ieq_weights.append(float(ieq_model_obj.lghtg_weight))
                elif category == 'IAQ':
                    ieq_weights.append(float(ieq_model_obj.iaq_weight))
                elif category == 'Acoustics':
                    ieq_weights.append(float(ieq_model_obj.acc_weight))
        else: #otherwise, just weight the existing categories equally
            eqi_alert = True
            for category in ieq_data_categories:
                #return HttpResponse(1/len(ieq_data_categories))
                ieq_weights.append(float(1)/len(ieq_data_categories))
        ieq_weights = np.array(ieq_weights).reshape(len(ieq_weights),1)
        ieq_cat_data = {}
        seriesData1 = []
        seriesData2 = []
        seriesData = []
        max_stack = 0
        qc1_data, qc2_data, qc3_data, qc4_data, qc5_data = {},{},{},{},{}
        categories = []
        scorecard = {'IAQ':[None,'badge-error'],'Acoustics':[None,'badge-error'],'Thermal Comfort':[None,'badge-error'],'Lighting':[None,'badge-error']}
        for category in ieq_data_categories:
            categories.append(category)
            qc1_sum = qc2_sum = qc3_sum = qc4_sum = qc5_sum = ieq_obj_cnt = 0 
            #get the saved ieq data objects that match a particular category and loop through the space types
            ieq_data_obj = IeqData.objects.filter(project=project_obj, ieq_category=category).filter(ieq_space__model=ieq_model_obj).distinct()
            for ieq_obj in ieq_data_obj:
                ieq_obj_cnt += 1
                #add together the qc values for each space type for the purposes of the scorecard. this is not spacetype weight intelligent yet
                qc1_sum += float(ieq_obj.quality_cat1) if isinstance(ieq_obj.quality_cat1, types.NoneType) == False else 0
                qc2_sum += float(ieq_obj.quality_cat2) if isinstance(ieq_obj.quality_cat2, types.NoneType) == False else 0
                qc3_sum += float(ieq_obj.quality_cat3) if isinstance(ieq_obj.quality_cat3, types.NoneType) == False else 0
                qc4_sum += float(ieq_obj.quality_cat4) if isinstance(ieq_obj.quality_cat4, types.NoneType) == False else 0
                qc5_sum += float(ieq_obj.quality_cat5) if isinstance(ieq_obj.quality_cat5, types.NoneType) == False else 0
                try: #add to an existing space type (stack) if one exists
                    qc1_data[str(ieq_obj.ieq_space)][category] = float(ieq_obj.quality_cat1) if isinstance(ieq_obj.quality_cat1, types.NoneType) == False else 0
                    qc2_data[str(ieq_obj.ieq_space)][category] = float(ieq_obj.quality_cat2) if isinstance(ieq_obj.quality_cat2, types.NoneType) == False else 0
                    qc3_data[str(ieq_obj.ieq_space)][category] = float(ieq_obj.quality_cat3) if isinstance(ieq_obj.quality_cat3, types.NoneType) == False else 0
                    qc4_data[str(ieq_obj.ieq_space)][category] = float(ieq_obj.quality_cat4) if isinstance(ieq_obj.quality_cat4, types.NoneType) == False else 0
                    qc5_data[str(ieq_obj.ieq_space)][category] = float(ieq_obj.quality_cat5) if isinstance(ieq_obj.quality_cat5, types.NoneType) == False else 0
                except: #otherwise create a new one
                    qc1_data[str(ieq_obj.ieq_space)] = {category: float(ieq_obj.quality_cat1) if isinstance(ieq_obj.quality_cat1, types.NoneType) == False else 0}
                    qc2_data[str(ieq_obj.ieq_space)] = {category: float(ieq_obj.quality_cat2) if isinstance(ieq_obj.quality_cat2, types.NoneType) == False else 0}
                    qc3_data[str(ieq_obj.ieq_space)] = {category: float(ieq_obj.quality_cat3) if isinstance(ieq_obj.quality_cat3, types.NoneType) == False else 0}
                    qc4_data[str(ieq_obj.ieq_space)] = {category: float(ieq_obj.quality_cat4) if isinstance(ieq_obj.quality_cat4, types.NoneType) == False else 0}
                    qc5_data[str(ieq_obj.ieq_space)] = {category: float(ieq_obj.quality_cat5) if isinstance(ieq_obj.quality_cat5, types.NoneType) == False else 0}
            #compute overall score for an ieq category. this method is based on Marino, but is not actually used there. Should discuss logic behind this...
            if ieq_model == 4:
                score = round(qc1_sum/ieq_obj_cnt,0)
                
            else:
                score = round(qc1_sum/ieq_obj_cnt + (.7*qc2_sum/ieq_obj_cnt) + (.35 * qc3_sum/ieq_obj_cnt),0)
            if score >= 66.7:
                badge = 'badge-success'
            elif score >= 33.3:
                badge = 'badge-warning'
            else:
                badge = 'badge-error'
            scorecard[category] = [score,badge]
        
        ieq_space_obj = IeqSpace.objects.get(model=ieq_model_obj, space_type='Default')
        if isinstance(ieq_space_obj.qc5_tc_summer_condition_low, types.NoneType) == False:
            colors = [['green', 'yellow', 'orange', 'red', 'purple'],['#43bd79', '#c5c745', '#c78e45', '#c75745', 'purple']]
        elif isinstance(ieq_space_obj.qc4_tc_summer_condition_low, types.NoneType) == False:
            colors = [['green', 'yellow', 'orange', 'red'],['#43bd79', '#c5c745', '#c78e45', '#c75745']]
        elif isinstance(ieq_space_obj.qc3_tc_summer_condition_low, types.NoneType) == False:
            colors = [['green', 'yellow', 'red'],['#43bd79', '#c5c745', '#c75745']]
        else:
            colors = [['green', 'red'],['#43bd79', '#c75745'], ['#00ff33', '#ff9999'], ['#336633','#996666']]
        
        qc_matrix = {}
        qc_data = [qc1_data, qc2_data, qc3_data, qc4_data, qc5_data]
        for i in reversed(xrange(len(qc_data))):
            stack = 0
            color_cnt = 1
            for space_type in qc_data[i]:
                ieq_series_data = []
                for category in categories:
                    try:
                        ieq_series_data.append(qc_data[i][space_type][category])
                    except:
                        ieq_series_data.append(0)
                try:
                    qc_matrix[space_type].append(ieq_series_data)
                except:
                    qc_matrix[space_type] = [ieq_series_data]
                if sum(ieq_series_data) != 0:
                    if str(space_type) == 'Default': #fix the default label to be more meaningful
                        space_type = 'Default and other space types'
                    if stack == 0: #split into different lists in order to maintain correct order for legend
                        seriesData1.append({'name': 'Assessment Class ' + str(i+1) + ': ' + str(space_type), 'color': colors[0][i],'data':ieq_series_data, 'stack': stack})
                    else:
                        seriesData2.append({'name': 'Assessment Class ' + str(i+1) + ': ' + str(space_type), 'color': colors[color_cnt][i],'data':ieq_series_data, 'stack': stack})
                        if color_cnt < 4: #this is a pretty lame way of doing this--the color sets need work. 
                            color_cnt += 1
                        else:
                            color_cnt = 1
                stack += 1
        seriesData = seriesData1 + seriesData2
        eqi = {}
        #return HttpResponse(simplejson.dumps(qc_matrix),mimetype="application/json")
        #log = qc_matrix
        for space_type in qc_matrix:
            eqi_check = True #this function needs work...
            cat_val_list = [[],[],[],[]]
            for model_class in qc_matrix[space_type]: 
                for i in xrange(len(model_class)):
                    cat_val_list[i].append(model_class[i])
            for cat_list in cat_val_list:
                if sum(cat_list) == 0:
                    eqi_check = False
            if eqi_check: 
                i_matrix = np.array(qc_matrix[space_type])
                dp = np.dot(i_matrix, ieq_weights)
                dp = dp.reshape(1,5).tolist()
                dp = dp[0] #not sure why this returns a list within a list
                dp.reverse()
                if ieq_model == 4:
                    eqi[space_type] = round(dp[0],0)
                else:
                    eqi[space_type] = round(dp[0] + (.7*dp[1]) + (.35*dp[2]),0)    
                ieq_space_obj = IeqSpace.objects.get(model=ieq_model_obj, space_type=space_type)
                if ieq_space_obj.weight != '':
                    st_weights.append(float(ieq_space_obj.weight))
                else:
                    bqi_alert = True
        
        #compute bqi if there is more than one space type
        if len(eqi) > 1:
            eqi_l = []
            if bqi_alert:
                st_weights = [] #reset weights
            for space_type in eqi: #right now just setting equal weights for each space_type
                eqi_l.append(eqi[space_type])
                if bqi_alert:
                    st_weights.append(float(1)/len(eqi))
            eqi_l = np.array(eqi_l)
            st_weights = np.array(st_weights)
            bqi = np.dot(eqi_l, st_weights)
            bqi = round(bqi,1)
        else:
            bqi = False
        
        try:
            image_url = project_obj.image.url
        except:
            image_url = False
        #add survey results
        survey_list = ['survey_tc', 'survey_iaq', 'survey_lighting', 'survey_acoustics','survey_tc_bm', 'survey_iaq_bm', 'survey_lighting_bm', 'survey_acoustics_bm']
        for cat in survey_list:
            score = eval('project_obj.' + cat)
            if score >= 66.7:
                badge = 'badge-success'
            elif score >= 33.3:
                badge = 'badge-warning'
            else:
                badge = 'badge-error'
            scorecard[cat] = [score, badge]
        #building info
        bi_name = project_obj.building
        bi_city = project_obj.city
        bi_area = project_obj.gross_floor_area
        bi_building_type = project_obj.building_type    
        return HttpResponse(simplejson.dumps({'seriesData': seriesData, 'categories': categories, 'alert': False, 'instance': 0,'eqi': eqi, 'bqi': bqi, 'eqi_alert': eqi_alert,'bqi_alert': bqi_alert, 'image_url': image_url, 'scorecard': scorecard, 'log':log, 'bi_name':bi_name, 'bi_area':bi_area,'bi_city':bi_city, 'bi_building_type':bi_building_type}),mimetype="application/json")  

    c = {'user': user,
         'projectF': projectF,
         'ieq_model': ieqModelFD
         }
    return render_to_response('scorecard.html',c)

@login_required
def scorecardSetup(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    projectF = make_project_form(groupL)
    ieqModelFD = IeqModelFD(auto_id="id_ieqModel_%s")
    c = {'user': user,
         'projectF': projectF,
         'ieq_model': ieqModelFD
         }
    if request.method == "POST":
        try:
            post_data = simplejson.loads(request.body)
        except:
            post_data = request.POST
        if post_data['select'] == 'readSurvey':
            projectObj = Project.objects.get(pk=post_data['projectId'])
            surveyObj = ProjectSurveyForm(instance=projectObj)
            return render_to_response('surveyInline.html',{'survey':surveyObj})
        elif post_data['select'] == 'submitSurvey':
            projectObj = Project.objects.get(pk=post_data['projectId'])
            surveyObj = ProjectSurveyForm(post_data['surveyForm'],instance=projectObj)
            if surveyObj.is_valid():
                surveyObj.save()
                saveStatus = "Saved successfully"
            else:
                saveStatus = "Check form for errors"
            return render_to_response('surveyInline.html',{'survey':surveyObj, 'saveStatus':saveStatus})
        elif post_data['select'] == 'changeModel':
            smodelFD = make_IeqSpaceFD(post_data['modelId'], False, False)
            return render_to_response('scSetupInline.html',{'ieq_space':smodelFD})
        elif post_data['select'] == 'addSt':
            stModel = IeqModelDef
            smodelFD = make_IeqSpaceFD(post_data['modelId'], False, False)
            return render_to_response('scSetupInline.html',{'stModel':stModel,'ieq_space':smodelFD})
        elif post_data['select'] == 'submitSt':
            try: #check for existing st model
                a = IeqSpace.objects.get(model=post_data['modelId'],space_type=post_data['space_type'])
            except:
                modelA = IeqModel.objects.get(pk=post_data['modelId'])
                a = IeqSpace(model=modelA)
            stModel = IeqModelDef(post_data['stForm'], instance=a)
            if stModel.is_valid():
                stModel.save()
                newStA = IeqSpace.objects.latest('id')
                smodelFD = make_IeqSpaceFD(post_data['modelId'], post_data['ieqSpaceForm'], newStA)
                saveStatus = "Saved successfully"
            else:
                smodelFD = make_IeqSpaceFD(post_data['modelId'], post_data['ieqSpaceForm'], False)
                saveStatus = "Check form for errors"
            return render_to_response('scSetupInline.html',{'stModel':stModel, 'saveStatus': saveStatus, 'ieq_space':smodelFD})
        elif post_data['select'] == 'deleteSt':
            smodelFD = make_IeqSpaceFD(post_data['modelId'],False, False)
            try:
                stModel = IeqSpace.objects.get(model=post_data['modelId'],space_type=post_data['space_type'])
                stModel.delete()
                saveStatus = "Deleted successfully" #this doesn't actually show up, oh well...
            except:
                saveStatus = "Problem deleting device instance"
            return render_to_response('scSetupInline.html',{'saveStatus': saveStatus, 'ieq_space':smodelFD})
        elif post_data['select'] == 'changeSt':
            smodelFD = make_IeqSpaceFD(post_data['modelId'], post_data['ieqSpaceForm'], False)
            try:
                a = IeqSpace.objects.get(model=post_data['modelId'],space_type=post_data['space_type'])
                stModel = IeqModelDef(instance=a)
            except:
                stModel = IeqModelDef
            return render_to_response('scSetupInline.html',{'stModel':stModel, 'ieq_space':smodelFD})
    
    else:
        return render_to_response('scorecardSetup.html',c)
    
@login_required
def report(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    f = make_project_formd(groupL)
    c = {'user': user,
     'projectF': f,
     }
    if request.method == 'POST':
        if 'report_content' in request.POST:
            result = file('/opt/bpe_toolkit/staticStore/userData/report_'+str(user)+'_.pdf', 'wb')
            pdf = pisa.CreatePDF(cStringIO.StringIO(str(request.POST['report_content'])), result)
            result.close()
            return HttpResponse('http://smap.cbe.berkeley.edu/static/userData/report_'+str(user)+'_.pdf')
        else: #generate report html
            post_data = simplejson.loads(request.body)
            projectId = post_data['projectId']
            project_obj = Project.objects.get(pk = projectId)
            #scorecard
            
            #building information
            flr_model = make_floorForm(projectId)
            bi_name = project_obj.building
            bi_city = project_obj.city
            bi_area = project_obj.gross_floor_area
            bi_building_type = project_obj.building_type
            bi_image = project_obj.image.url
            floors = project_obj.floors.all()
            
            map_summary_objects = ChartImage.objects.filter(project=projectId, type='Map-summary')
            bi_maps = []
            for obj in map_summary_objects:
                bi_maps.append({'caption':obj.caption, 'url':obj.map_image.url})
            #user chart section
            user_charts = []
            for chart in post_data['included_user_charts']:
                chart_obj = ChartImage.objects.get(name=chart)
                user_charts.append({'url':chart_obj.image_url, 'category': chart_obj.pmp_category, 'caption':chart_obj.caption, 'legend': chart_obj.legend})
            #determine counts for each category--don't include heading if they aren't any charts
            user_chart_categories = {'lighting':0,'acoustics':0,'tc':0, 'iaq':0}
            for chart in user_charts:
                if chart['category'] == 'Lighting':
                    user_chart_categories['lighting'] += 1
                if chart['category'] == 'Acoustics':
                    user_chart_categories['acoustics'] += 1
                if chart['category'] == 'IAQ':
                    user_chart_categories['iaq'] += 1
                if chart['category'] == 'Thermal Comfort':
                    user_chart_categories['tc'] += 1     
            
            c = {'user_charts':user_charts,
             'bi_name': bi_name,
             'bi_city': bi_city,
             'bi_area':bi_area,
             'bi_building_type': bi_building_type,
             'bi_image': bi_image,
             'bi_maps': bi_maps,
             'user_chart_categories': user_chart_categories,
             }
            return render_to_response('reportInline.html',c)
    else:
        return render_to_response('reportHelper.html',c)

@login_required
def weather(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    f = make_project_formd(groupL)
    c = {'user': user,
     'projectF': f,
     }
    if request.method == "GET":
        if 'select' in request.GET:
            if request.GET['select'] == 'restart':
                r = subprocess.call('/opt/bpe_toolkit/pmp/scripts/startWeather1.sh')
                success = 'Successfully restarted weather sources'
                return HttpResponse(success)
            try:
                project_obj = Project.objects.get(pk=request.GET['projectId'])
            except:
                success = 'Please select a project before proceeding'
                return HttpResponse(success)
            station = request.GET['station']
            if station != '':
                if request.GET['select'] == 'start':
                    fp = open('/opt/bpe_toolkit/pmp/scripts/wunderground.ini', 'r')
                    fp_contents = fp.read()
                    project_found = project_obj.name in fp_contents
                    fp.close()
                    if project_found:
                        fp = open('/opt/bpe_toolkit/pmp/scripts/wunderground.ini', 'r')
                        fp_lines = iter(fp.readlines())
                        fp.close()
                        fp = open('/opt/bpe_toolkit/pmp/scripts/wunderground.ini', 'w')
                        for line in fp_lines:
                            if project_obj.name in line:
                                fp.write(line)
                                fp.write(next(fp_lines))
                                next_line = next(fp_lines)
                                if station in next_line:
                                    fp.write(next_line)
                                    break
                                else:
                                    fp.write(next_line.rstrip('\n') + station + ',\n')
                                    fp.write(next(fp_lines))
                            else:
                                fp.write(line)
                        fp.close()
                    else:
                        fp = open('/opt/bpe_toolkit/pmp/scripts/wunderground.ini', 'a')
                        fp.write('\n\n[/weather-'+project_obj.name + ']\ntype = smap.drivers.wundergroundCBE.WunderGround\nID = ' + station + ',\nMetadata/Extra/Project = ' + project_obj.name)
                        fp.close()
                    
                    r = subprocess.call('/opt/bpe_toolkit/pmp/scripts/startWeather1.sh')
                    success = 'Successfully started the weather sMAP source for ' + station
                else:
                    fp = open('/opt/bpe_toolkit/pmp/scripts/wunderground.ini', 'r')
                    fp_lines = iter(fp.readlines())
                    fp.close()
                    fp = open('/opt/bpe_toolkit/pmp/scripts/wunderground.ini', 'w')
                    for line in fp_lines:
                        if project_obj.name in line:
                            fp.write(line)
                            fp.write(next(fp_lines))
                            next_line = next(fp_lines)
                            if station in next_line:
                                next_line = next_line.replace(station + ",","")
                                fp.write(next_line)
                                station_found = True
                            fp.write(next(fp_lines))
                        else:
                            fp.write(line)
                    fp.close()
                    if station_found:
                        r = subprocess.call('/opt/bpe_toolkit/pmp/scripts/startWeather1.sh')
                        success = 'Successfully stopped the weather sMAP source for ' + station
                    else:
                        success = 'The station you specified was not found for this project'    
            else:
                success = 'Make sure you have entered a valid station ID'
            return HttpResponse(success)
        elif 'q_type' in request.GET: #historical data
            try:
                project_obj = Project.objects.get(pk=request.GET['projectId'])
            except:
                success = 'Please select a project before proceeding'
                return HttpResponse(success)
            if request.GET['q_input1'] != '' and request.GET['q_input2'] != '':
                city = request.GET['q_input1']
                fp = open('/opt/bpe_toolkit/pmp/scripts/wundergroundHistorySaved.ini', 'r')
                fp_content = fp.read()
                fp.close()
                fp = open('/opt/bpe_toolkit/pmp/scripts/wundergroundHistory.ini', 'w')
                fp.write(fp_content)
                if request.GET['q_type'] == 'zipcode':
                    q_string = request.GET['q_input2']
                else:
                    q_string = 'pws:'+request.GET['q_input2']
                random.seed()
                port_add = random.randint(1,19)
                fp.write('\n\n[/'+city+' History]\ntype = smap.drivers.wundergroundHistory.WunderGroundHistory\nq_type = /q/' + q_string + '.json\nstart_date = ' + request.GET['start_date'] + '\nend_date = ' + request.GET['end_date'] + '\nMetadata/Extra/Project = ' + project_obj.name + '\n\n[server]\nPort = ' + str(8080+port_add))
                fp.close()
                r = subprocess.call('/opt/bpe_toolkit/pmp/scripts/startWeatherHistory1.sh') 
                success = 'You have successfully started to load historical data for ' + city + '. It may take a while for this process to complete.'
            else:
                success = 'Make sure you have filled out both input fields before proceeding'
            return HttpResponse(success)
        else:
            return render_to_response('weather.html',c)

def energy(request):
    user = request.user
    userI = User.objects.get(username=user)
    groupL = userI.groups.all().values_list('pk', flat=True)
    f = make_project_formd(groupL)
    c = {'user': user,
     'projectF': f,
     }
    if request.method == "POST":
        if 'projectIdChange' in request.POST:
            configFileF = ConfigFileForm(auto_id='id_form_%s')
            configFileFD = ConfigFileFormDrop(auto_id='id_for_%s')
            configFileFD.fields['name'].queryset = ConfigFile.objects.filter(project=request.POST['projectIdChange'], type='economizer')
            c = {'configFileF' : configFileF, 'configFileFD' : configFileFD}
            return render_to_response('economizer_inline.html', c)
        post_data = simplejson.loads(request.body)
        if 'form' in post_data: #handle the loading and saving of economizer analysis mappings 
            configFileNames = ConfigFile.objects.all().values_list('name', flat=True)
            if post_data['form']['name'] in configFileNames:
                try:
                    a = ConfigFile.objects.get(name=post_data['form']['name'], type='economizer')
                    configFileF = ConfigFileForm(instance=a, auto_id='id_form_%s')
                except:
                    configFileF = ConfigFileForm(post_data['form'], auto_id='id_form_%s')
            else:
                configFileF = ConfigFileForm(post_data['form'], auto_id='id_form_%s')
            projectI = Project.objects.get(pk=int(post_data['form']['projectId']))
            configForm = configFileF.save(commit=False)
            configForm.project = projectI
            configForm.type = 'economizer'
            configForm.save()
            configFileFD = ConfigFileFormDrop(auto_id='id_for_%s')
            configFileFD.fields['name'].queryset = ConfigFile.objects.filter(project=int(post_data['form']['projectId']), type='economizer')
            f = open('/opt/bpe_toolkit/staticStore/userData/' + post_data['form']['name'] + '_' + str(configForm.pk) + '.json', 'w')
            #for whatever reason, the get_json function of jstree doesn't get the class attributes of the tree, so add it back to the file here
            f.write(simplejson.dumps(post_data['treeJSON']).replace("\" \"", "\"jstree-drop\"").replace("\"  \"", "\"jstree-drop\""))
            f.close()
            c = {'configFileF' : configFileF, 'configFileFD' : configFileFD}
            return render_to_response('economizer_inline.html', c)
        
        time_zone = tz.gettz(Project.objects.get(pk=post_data['projectId']).timezone)
        paths_dict = post_data['paths_dict']
        start = post_data['start']
        end = post_data['end']
        resample_s = post_data['resample_s']
        min_oa_frac = int(post_data['min_oa_frac'])/100
        success = False
        
        #check for chw_vlv
        if paths_dict['chw_vlv'] != '':
            chw_e = True
            chw_query = 'or Path = \"'+ paths_dict['chw_vlv'] + '\"'
        else:
            chw_e = False
            chw_query = ''
        
        data_dict = {'mat':[],'rat':[],'oat':[],'sat':[],'sat_stpt':[],'chw_vlv':[]}
        #econ_name = paths_dict['mat'].split('/')[3] #stupid hardcoding--needs to change according to project
        chart_dict = {'region1':[],'region2':[],'region3':[],'region4':[],'region5':[]}
        #return HttpResponse(econ_name)
        c = smap.archiver.client.SmapClient(base='http://new.openbms.org/backend', key=['WE4iJWG7k575AluJ9RJyAZs25UO72Xu0b4RA','SA2nYWuHrJxmPNK96pdLKhnSSYQSPdALkvnA'])
        #queryS = 'set Metadata/Extra/Economizer = \"' + econ_name + '\" where Path = \"' + paths_dict['mat'] + '\" or Path = \"'+ paths_dict['rat'] + '\" or Path = \"'+ paths_dict['oat'] + '\" or Path = \"'+ paths_dict['sat'] + '\" or Path = \"'+ paths_dict['sa_stpt'] + '\"'
        #setmeta = c.query(queryS)
        queryS = 'apply window(mean, field=\'minute\', width=' + str(int(resample_s)/60) + ') to data in (' + str(start) + ',' + str(end) + ') limit 10000000 where Path = \"' + paths_dict['mat'] + '\" or Path = \"'+ paths_dict['rat'] + '\" or Path = \"'+ paths_dict['oat'] + '\" or Path = \"'+ paths_dict['sat'] + '\" or Path = \"'+ paths_dict['sat_stpt'] + '\"' + chw_query  
        #queryS = 'apply window(first, field=\'second\', width=' + str(resample_s) + ') to data in (' + str(start) + ',' + str(end) + ') limit 10000000 where Metadata/Extra/Economizer = \"' + econ_name + '\"'
        #return HttpResponse(queryS)
        data = c.query(queryS)
        #return HttpResponse(data)
        for stream_data in data:
            try:
                data = stream_data['Readings']
                #filter data
                if not post_data['ad']:
                    wkd = post_data['wkd']
                    sh = post_data['sh']
                    eh = post_data['eh']
                    data = filterData(data, time_zone, wkd, sh, eh)
                for key in paths_dict:
                    if paths_dict[key] == stream_data['Path']:
                        data_dict[key] = data
                        break
                    else:
                        continue
                success = True
            except:
                success = data
        for i in xrange(len(data_dict['mat'])):
            try:
                oat = round(data_dict['oat'][i][1],2)
                rat = round(data_dict['rat'][i][1],2)
                sat = round(data_dict['sat'][i][1],2)
                mat = round(data_dict['mat'][i][1],2)
                sat_stpt = round(data_dict['sat_stpt'][i][1],1)
                if chw_e:
                    chw_vlv = round(data_dict['chw_vlv'][i][1],1)
                else:
                    chw_vlv = 999
                #region 1 -- economizer at min oa
                if (oat*min_oa_frac) + ((1-min_oa_frac)*rat) < sat_stpt:
                    chart_dict['region1'].append([(oat*min_oa_frac) + ((1-min_oa_frac)*rat),mat])
                #region 3 -- economizer 100% open
                elif oat > sat_stpt and oat < rat and chw_vlv < int(post_data['chw_vlv_adj']):
                    
                    chart_dict['region3'].append([oat,mat])
                #region 4 -- integrated operation
                elif oat > sat_stpt and oat < rat:
                    chart_dict['region4'].append([oat,mat])
                #region 5 -- economizer at min oa (high temp lockout)
                elif oat > rat:
                    chart_dict['region5'].append([(oat*min_oa_frac) + ((1-min_oa_frac)*rat),mat])
                #region 2 --economizer modulates with heating
                else:
                    chart_dict['region2'].append([sat_stpt,mat])
            except:
                continue
                #return HttpResponse(queryS)
        
        d = simplejson.dumps({'data':chart_dict, 'success': success})
        return HttpResponse(d, mimetype="application/json")
    return render_to_response('energyAnalysis.html',c)
    
def imp(request):
    post_data = simplejson.loads(request.body) 
    currentTime = datetime.datetime.utcnow()
    currentTime = int(calendar.timegm(currentTime.utctimetuple())) * 1000
    jsonData = {"/dh/dbt_imp01" : {
                              "Metadata" : {
                                            "SourceName" : "Electric IMP",
                                            "Location" : { "City" : "Berkeley" },
                                            "Extra" : {"Project" : "dh"}
                                            },
                              "Properties": {
                                             "UnitofMeasure": "F", 
                                             "ReadingType": "double"
                                             },
                              "Readings" : [[currentTime, post_data[0]*.9986+.0541]],
                              "uuid" : "b7bc0042-b50a-11e2-8602-000c29b20fba"
                              },
                "/dh/glb_imp01" : {
                              "Metadata" : {
                                            "SourceName" : "Electric IMP",
                                            "Location" : { "City" : "Berkeley" },
                                            "Extra" : {"Project" : "dh"}
                                            },
                              "Properties": {
                                             "UnitofMeasure": "F", 
                                             "ReadingType": "double"
                                             },
                              "Readings" : [[currentTime, post_data[1]*.9971+.4652]],
                              "uuid" : "89448e92-1431-11e3-8a4a-000c29b20fba"
                              },
                "/dh/co2_imp01" : {
                              "Metadata" : {
                                            "SourceName" : "Electric IMP",
                                            "Location" : { "City" : "Berkeley" },
                                            "Extra" : {"Project" : "dh"}
                                            },
                              "Properties": {
                                             "UnitofMeasure": "ppm", 
                                             "ReadingType": "double"
                                             },
                              "Readings" : [[currentTime, post_data[2]*500]],
                              "uuid" : "91a9f324-1431-11e3-be26-000c29b20fba"
                              },
                "/dh/rh_imp01" : {
                              "Metadata" : {
                                            "SourceName" : "Electric IMP",
                                            "Location" : { "City" : "Berkeley" },
                                            "Extra" : {"Project" : "dh"}
                                            },
                              "Properties": {
                                             "UnitofMeasure": "%", 
                                             "ReadingType": "double"
                                             },
                              "Readings" : [[currentTime, (post_data[3]/4.955-0.16)/0.0062]],
                              "uuid" : "94d67b4e-6ffd-11e3-92ca-000c29b20fba"
                              },
                 "/dh/pm_imp01" : {
                              "Metadata" : {
                                            "SourceName" : "Electric IMP",
                                            "Location" : { "City" : "Berkeley" },
                                            "Extra" : {"Project" : "dh"}
                                            },
                              "Properties": {
                                             "UnitofMeasure": ">1 micron particle conc. per 0.01 cf", 
                                             "ReadingType": "double"
                                             },
                              "Readings" : [[currentTime, post_data[4]]],
                              "uuid" : "53f91e94-6582-11e4-a2e5-000c29b20fba"
                              }
                }
    jsonData = simplejson.dumps(jsonData)
     
    url = 'http://new.openbms.org/backend/add/SA2nYWuHrJxmPNK96pdLKhnSSYQSPdALkvnA'
    req = urllib2.Request(url, jsonData, {'Content-Type': 'application/json'})
    f = urllib2.urlopen(req)
    f.close()

    return HttpResponse('done')

def testing(request):  
    #fp = open('/tmp/testing.txt','w')
    #fp.write(str(currentTime)+'\n')
    #fp.write(request.body)
    #fp.close()
    #query = ['Zone.objects.filter(project=projectId).filter(test__start_time__lte=start_date).filter(test__device__sensor__pmp_category=\'IAQ\')']
    #time_zone = tz.gettz(Project.objects.get(pk=7).timezone)
    #start_date = datetime.datetime.fromtimestamp(1348732800000/1000, time_zone)
    #test = Zone.objects.filter(project=7).filter(test__device__sensor__pmp_category='Acoustics',test__start_time__lte=start_date).distinct()#.values_list('orientation', flat=True)
    #test = serializers.serialize('json', test)
    return HttpResponse(simplejson.dumps({'test': test}),mimetype="application/json")
    #devices = Device.objects.filter(name__contains='HOBO').exclude(type='Fixed pole')
    #for device in devices:
    #    device.type = 'Plenum mote'
    #    device.save()

